From e98258b206327ceae711ce4da4db471660c9ea85 Mon Sep 17 00:00:00 2001 From: James Liu Date: Sun, 2 Jan 2022 15:31:15 -0500 Subject: [PATCH 01/13] Implement Dereff(Mut) on BufferVec. --- .../src/render_resource/buffer_vec.rs | 68 ++++++++++--------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/crates/bevy_render/src/render_resource/buffer_vec.rs b/crates/bevy_render/src/render_resource/buffer_vec.rs index ad8f5ff2adfe1..da2fc6a806de4 100644 --- a/crates/bevy_render/src/render_resource/buffer_vec.rs +++ b/crates/bevy_render/src/render_resource/buffer_vec.rs @@ -4,13 +4,15 @@ use crate::{ }; use bevy_core::{cast_slice, Pod}; use copyless::VecHelper; +use std::ops::{Deref, DerefMut}; use wgpu::BufferUsages; +/// A user-friendly wrapper around a [`Buffer`] that provides a `Vec`-like +/// interface for constructing the buffer. pub struct BufferVec { values: Vec, buffer: Option, capacity: usize, - item_size: usize, buffer_usage: BufferUsages, } @@ -21,12 +23,14 @@ impl Default for BufferVec { buffer: None, capacity: 0, buffer_usage: BufferUsages::all(), - item_size: std::mem::size_of::(), } } } impl BufferVec { + /// Creates a new [`BufferVec`] with the associated [`BufferUsages`]. + /// + /// This does not immediately allocate a buffer. pub fn new(buffer_usage: BufferUsages) -> Self { Self { buffer_usage, @@ -34,36 +38,41 @@ impl BufferVec { } } + /// Gets the reference to the underlying buffer, if one has been allocated. #[inline] pub fn buffer(&self) -> Option<&Buffer> { self.buffer.as_ref() } + /// Gets the capacity of the underlying buffer. + /// + /// Will return 0 if no buffer has been allocated yet. #[inline] - pub fn capacity(&self) -> usize { + pub fn buffer_capacity(&self) -> usize { self.capacity } - #[inline] - pub fn len(&self) -> usize { - self.values.len() - } - - #[inline] - pub fn is_empty(&self) -> bool { - self.values.is_empty() - } - - pub fn push(&mut self, value: T) -> usize { - let index = self.values.len(); - self.values.alloc().init(value); - index + /// Queues up a copy of the contents of the [`BufferVec`] into the underlying + /// buffer. + /// + /// If no buffer has been allocated yet or if the current size of the contents + /// exceeds the size of the underlying buffer, a new buffer will be allocated. + pub fn write_buffer(&mut self, device: &RenderDevice, queue: &RenderQueue) { + if self.values.is_empty() { + return; + } + self.reserve_buffer(self.values.len(), device); + if let Some(buffer) = &self.buffer { + let range = 0..std::mem::size_of::() * self.values.len(); + let bytes: &[u8] = cast_slice(&self.values); + queue.write_buffer(buffer, 0, &bytes[range]); + } } - pub fn reserve(&mut self, capacity: usize, device: &RenderDevice) { + fn reserve_buffer(&mut self, capacity: usize, device: &RenderDevice) { if capacity > self.capacity { self.capacity = capacity; - let size = self.item_size * capacity; + let size = std::mem::size_of::() * capacity; self.buffer = Some(device.create_buffer(&wgpu::BufferDescriptor { label: None, size: size as wgpu::BufferAddress, @@ -72,20 +81,17 @@ impl BufferVec { })); } } +} - pub fn write_buffer(&mut self, device: &RenderDevice, queue: &RenderQueue) { - if self.values.is_empty() { - return; - } - self.reserve(self.values.len(), device); - if let Some(buffer) = &self.buffer { - let range = 0..self.item_size * self.values.len(); - let bytes: &[u8] = cast_slice(&self.values); - queue.write_buffer(buffer, 0, &bytes[range]); - } +impl Deref for BufferVec { + type Target = Vec; + fn deref(&self) -> &Self::Target { + &self.values } +} - pub fn clear(&mut self) { - self.values.clear(); +impl DerefMut for BufferVec { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.values } } From 53209fe18723f826b8002229b5eaccdcf0fc7e19 Mon Sep 17 00:00:00 2001 From: James Liu Date: Tue, 4 Jan 2022 18:15:45 -0500 Subject: [PATCH 02/13] Implement Deref(Mut) on UniformVec --- crates/bevy_pbr/src/render/light.rs | 5 +- .../src/render_resource/uniform_vec.rs | 75 +++++++++---------- 2 files changed, 37 insertions(+), 43 deletions(-) diff --git a/crates/bevy_pbr/src/render/light.rs b/crates/bevy_pbr/src/render/light.rs index 562c9b6d2031c..cafde310e598d 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -931,7 +931,7 @@ impl ViewClusterBindings { let component = self.n_offsets & ((1 << 2) - 1); let packed = pack_offset_and_count(offset, count); - self.cluster_offsets_and_counts.get_mut(0)[array_index][component] = packed; + self.cluster_offsets_and_counts[0][array_index][component] = packed; self.n_offsets += 1; } @@ -946,8 +946,7 @@ impl ViewClusterBindings { let sub_index = self.n_indices & ((1 << 2) - 1); let index = index as u32 & POINT_LIGHT_INDEX_MASK; - self.cluster_light_index_lists.get_mut(0)[array_index][component] |= - index << (8 * sub_index); + self.cluster_light_index_lists[0][array_index][component] |= index << (8 * sub_index); self.n_indices += 1; } diff --git a/crates/bevy_render/src/render_resource/uniform_vec.rs b/crates/bevy_render/src/render_resource/uniform_vec.rs index f31e7e258d6a2..bc0e5963565f0 100644 --- a/crates/bevy_render/src/render_resource/uniform_vec.rs +++ b/crates/bevy_render/src/render_resource/uniform_vec.rs @@ -3,7 +3,10 @@ use crate::{ render_resource::Buffer, renderer::{RenderDevice, RenderQueue}, }; -use std::num::NonZeroU64; +use std::{ + num::NonZeroU64, + ops::{Deref, DerefMut}, +}; use wgpu::{BindingResource, BufferBinding, BufferDescriptor, BufferUsages}; pub struct UniformVec { @@ -11,7 +14,6 @@ pub struct UniformVec { scratch: Vec, uniform_buffer: Option, capacity: usize, - item_size: usize, } impl Default for UniformVec { @@ -21,13 +23,15 @@ impl Default for UniformVec { scratch: Vec::new(), uniform_buffer: None, capacity: 0, - item_size: (T::std140_size_static() + ::Output::ALIGNMENT - 1) - & !(::Output::ALIGNMENT - 1), } } } impl UniformVec { + const ITEM_SIZE: usize = + (std::mem::size_of::() + ::Output::ALIGNMENT - 1) + & !(::Output::ALIGNMENT - 1); + #[inline] pub fn uniform_buffer(&self) -> Option<&Buffer> { self.uniform_buffer.as_ref() @@ -38,20 +42,10 @@ impl UniformVec { Some(BindingResource::Buffer(BufferBinding { buffer: self.uniform_buffer()?, offset: 0, - size: Some(NonZeroU64::new(self.item_size as u64).unwrap()), + size: Some(NonZeroU64::new(Self::ITEM_SIZE as u64).unwrap()), })) } - #[inline] - pub fn len(&self) -> usize { - self.values.len() - } - - #[inline] - pub fn is_empty(&self) -> bool { - self.values.is_empty() - } - #[inline] pub fn capacity(&self) -> usize { self.capacity @@ -63,14 +57,23 @@ impl UniformVec { index } - pub fn get_mut(&mut self, index: usize) -> &mut T { - &mut self.values[index] + pub fn write_buffer(&mut self, device: &RenderDevice, queue: &RenderQueue) { + if self.values.is_empty() { + return; + } + self.reserve_buffer(self.values.len(), device); + if let Some(uniform_buffer) = &self.uniform_buffer { + let range = 0..Self::ITEM_SIZE * self.values.len(); + let mut writer = std140::Writer::new(&mut self.scratch[range.clone()]); + writer.write(self.values.as_slice()).unwrap(); + queue.write_buffer(uniform_buffer, 0, &self.scratch[range]); + } } - pub fn reserve(&mut self, capacity: usize, device: &RenderDevice) -> bool { + fn reserve_buffer(&mut self, capacity: usize, device: &RenderDevice) -> bool { if capacity > self.capacity { self.capacity = capacity; - let size = self.item_size * capacity; + let size = Self::ITEM_SIZE * capacity; self.scratch.resize(size, 0); self.uniform_buffer = Some(device.create_buffer(&BufferDescriptor { label: None, @@ -84,25 +87,21 @@ impl UniformVec { } } - pub fn write_buffer(&mut self, device: &RenderDevice, queue: &RenderQueue) { - if self.values.is_empty() { - return; - } - self.reserve(self.values.len(), device); - if let Some(uniform_buffer) = &self.uniform_buffer { - let range = 0..self.item_size * self.values.len(); - let mut writer = std140::Writer::new(&mut self.scratch[range.clone()]); - writer.write(self.values.as_slice()).unwrap(); - queue.write_buffer(uniform_buffer, 0, &self.scratch[range]); - } + pub fn values(&self) -> &[T] { + &self.values } +} - pub fn clear(&mut self) { - self.values.clear(); +impl Deref for UniformVec { + type Target = Vec; + fn deref(&self) -> &Self::Target { + &self.values } +} - pub fn values(&self) -> &[T] { - &self.values +impl DerefMut for UniformVec { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.values } } @@ -146,12 +145,8 @@ impl DynamicUniformVec { #[inline] pub fn push(&mut self, value: T) -> u32 { - (self.uniform_vec.push(DynamicUniform(value)) * self.uniform_vec.item_size) as u32 - } - - #[inline] - pub fn reserve(&mut self, capacity: usize, device: &RenderDevice) { - self.uniform_vec.reserve(capacity, device); + (self.uniform_vec.push(DynamicUniform(value)) * UniformVec::>::ITEM_SIZE) + as u32 } #[inline] From 94bc29fd39c70e9a923fd57c40b273707020e16d Mon Sep 17 00:00:00 2001 From: James Liu Date: Tue, 4 Jan 2022 19:03:50 -0500 Subject: [PATCH 03/13] Add missing documentation to UniformVec --- .../src/render_resource/uniform_vec.rs | 37 +++++++++++++++---- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/crates/bevy_render/src/render_resource/uniform_vec.rs b/crates/bevy_render/src/render_resource/uniform_vec.rs index bc0e5963565f0..6dfb1f95726aa 100644 --- a/crates/bevy_render/src/render_resource/uniform_vec.rs +++ b/crates/bevy_render/src/render_resource/uniform_vec.rs @@ -9,6 +9,11 @@ use std::{ }; use wgpu::{BindingResource, BufferBinding, BufferDescriptor, BufferUsages}; +/// A user-friendly wrapper around a [`Buffer`] that provides a `Vec`-like +/// interface for constructing the buffer. +/// +/// Intended strictly for use with uniform buffers. For other use cases, +/// see [`BufferVec`] instead. pub struct UniformVec { values: Vec, scratch: Vec, @@ -32,20 +37,26 @@ impl UniformVec { (std::mem::size_of::() + ::Output::ALIGNMENT - 1) & !(::Output::ALIGNMENT - 1); + /// Gets the reference to the underlying buffer, if one has been allocated. #[inline] - pub fn uniform_buffer(&self) -> Option<&Buffer> { + pub fn buffer(&self) -> Option<&Buffer> { self.uniform_buffer.as_ref() } + /// Creates a binding for the underlying buffer. + /// Returns `None` if no buffer has been allocated. #[inline] pub fn binding(&self) -> Option { Some(BindingResource::Buffer(BufferBinding { - buffer: self.uniform_buffer()?, + buffer: self.buffer()?, offset: 0, size: Some(NonZeroU64::new(Self::ITEM_SIZE as u64).unwrap()), })) } + /// Gets the capacity of the underlying buffer. + /// + /// Will return 0 if no buffer has been allocated yet. #[inline] pub fn capacity(&self) -> usize { self.capacity @@ -57,6 +68,11 @@ impl UniformVec { index } + /// Queues up a copy of the contents of the [`UniformVec`] into the underlying + /// buffer. + /// + /// If no buffer has been allocated yet or if the current size of the contents + /// exceeds the size of the underlying buffer, a new buffer will be allocated. pub fn write_buffer(&mut self, device: &RenderDevice, queue: &RenderQueue) { if self.values.is_empty() { return; @@ -86,10 +102,6 @@ impl UniformVec { false } } - - pub fn values(&self) -> &[T] { - &self.values - } } impl Deref for UniformVec { @@ -118,11 +130,14 @@ impl Default for DynamicUniformVec { } impl DynamicUniformVec { + /// Gets the reference to the underlying buffer, if one has been allocated. #[inline] - pub fn uniform_buffer(&self) -> Option<&Buffer> { - self.uniform_vec.uniform_buffer() + pub fn buffer(&self) -> Option<&Buffer> { + self.uniform_vec.buffer() } + /// Creates a binding for the underlying buffer. + /// Returns `None` if no buffer has been allocated. #[inline] pub fn binding(&self) -> Option { self.uniform_vec.binding() @@ -138,6 +153,7 @@ impl DynamicUniformVec { self.uniform_vec.is_empty() } + /// Gets the capacity of the underlying buffer, in bytes. #[inline] pub fn capacity(&self) -> usize { self.uniform_vec.capacity() @@ -149,6 +165,11 @@ impl DynamicUniformVec { as u32 } + /// Queues up a copy of the contents of the [`UniformVec`] into the underlying + /// buffer. + /// + /// If no buffer has been allocated yet or if the current size of the contents + /// exceeds the size of the underlying buffer, a new buffer will be allocated. #[inline] pub fn write_buffer(&mut self, device: &RenderDevice, queue: &RenderQueue) { self.uniform_vec.write_buffer(device, queue); From b4a4cc783731c1540c9a7e2353db4022e88ce859 Mon Sep 17 00:00:00 2001 From: James Liu Date: Tue, 4 Jan 2022 19:29:23 -0500 Subject: [PATCH 04/13] Fix docs and CI checks --- crates/bevy_render/src/render_resource/uniform_vec.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/crates/bevy_render/src/render_resource/uniform_vec.rs b/crates/bevy_render/src/render_resource/uniform_vec.rs index 6dfb1f95726aa..1a86afc03f143 100644 --- a/crates/bevy_render/src/render_resource/uniform_vec.rs +++ b/crates/bevy_render/src/render_resource/uniform_vec.rs @@ -11,9 +11,11 @@ use wgpu::{BindingResource, BufferBinding, BufferDescriptor, BufferUsages}; /// A user-friendly wrapper around a [`Buffer`] that provides a `Vec`-like /// interface for constructing the buffer. -/// -/// Intended strictly for use with uniform buffers. For other use cases, -/// see [`BufferVec`] instead. +/// +/// Intended strictly for use with uniform buffers. For other use cases, +/// see [`BufferVec`][buffervec] instead. +/// +/// [buffervec]: crate::render_resource::BufferVec pub struct UniformVec { values: Vec, scratch: Vec, From b2b7a5d995f03793aa24d46dfdf8d5fba59dd0c2 Mon Sep 17 00:00:00 2001 From: James Liu Date: Tue, 4 Jan 2022 21:05:00 -0500 Subject: [PATCH 05/13] Make the buffer_capacity name consistent --- crates/bevy_render/src/render_resource/uniform_vec.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bevy_render/src/render_resource/uniform_vec.rs b/crates/bevy_render/src/render_resource/uniform_vec.rs index 1a86afc03f143..4f08478d22ad6 100644 --- a/crates/bevy_render/src/render_resource/uniform_vec.rs +++ b/crates/bevy_render/src/render_resource/uniform_vec.rs @@ -60,7 +60,7 @@ impl UniformVec { /// /// Will return 0 if no buffer has been allocated yet. #[inline] - pub fn capacity(&self) -> usize { + pub fn buffer_capacity(&self) -> usize { self.capacity } @@ -157,8 +157,8 @@ impl DynamicUniformVec { /// Gets the capacity of the underlying buffer, in bytes. #[inline] - pub fn capacity(&self) -> usize { - self.uniform_vec.capacity() + pub fn buffer_capacity(&self) -> usize { + self.uniform_vec.buffer_capacity() } #[inline] From a01ed4bddda8c4682ab04f9b0e65140092ce76b2 Mon Sep 17 00:00:00 2001 From: james7132 Date: Fri, 25 Feb 2022 02:26:52 -0800 Subject: [PATCH 06/13] Fix CI --- crates/bevy_render/src/render_resource/buffer_vec.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/bevy_render/src/render_resource/buffer_vec.rs b/crates/bevy_render/src/render_resource/buffer_vec.rs index da2fc6a806de4..72a96aeb319a0 100644 --- a/crates/bevy_render/src/render_resource/buffer_vec.rs +++ b/crates/bevy_render/src/render_resource/buffer_vec.rs @@ -3,7 +3,6 @@ use crate::{ renderer::{RenderDevice, RenderQueue}, }; use bevy_core::{cast_slice, Pod}; -use copyless::VecHelper; use std::ops::{Deref, DerefMut}; use wgpu::BufferUsages; From 6cb745b9d5e9f75d5c82cbf73436a693e2f6632a Mon Sep 17 00:00:00 2001 From: james7132 Date: Wed, 2 Mar 2022 03:50:20 -0800 Subject: [PATCH 07/13] Remove capacity from UniformVec --- crates/bevy_render/src/render_resource/buffer_vec.rs | 8 -------- crates/bevy_render/src/render_resource/uniform_vec.rs | 6 ++---- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/crates/bevy_render/src/render_resource/buffer_vec.rs b/crates/bevy_render/src/render_resource/buffer_vec.rs index 72a96aeb319a0..3f3e59979d802 100644 --- a/crates/bevy_render/src/render_resource/buffer_vec.rs +++ b/crates/bevy_render/src/render_resource/buffer_vec.rs @@ -43,14 +43,6 @@ impl BufferVec { self.buffer.as_ref() } - /// Gets the capacity of the underlying buffer. - /// - /// Will return 0 if no buffer has been allocated yet. - #[inline] - pub fn buffer_capacity(&self) -> usize { - self.capacity - } - /// Queues up a copy of the contents of the [`BufferVec`] into the underlying /// buffer. /// diff --git a/crates/bevy_render/src/render_resource/uniform_vec.rs b/crates/bevy_render/src/render_resource/uniform_vec.rs index 4f08478d22ad6..fb921bb513360 100644 --- a/crates/bevy_render/src/render_resource/uniform_vec.rs +++ b/crates/bevy_render/src/render_resource/uniform_vec.rs @@ -20,7 +20,6 @@ pub struct UniformVec { values: Vec, scratch: Vec, uniform_buffer: Option, - capacity: usize, } impl Default for UniformVec { @@ -29,7 +28,6 @@ impl Default for UniformVec { values: Vec::new(), scratch: Vec::new(), uniform_buffer: None, - capacity: 0, } } } @@ -61,7 +59,7 @@ impl UniformVec { /// Will return 0 if no buffer has been allocated yet. #[inline] pub fn buffer_capacity(&self) -> usize { - self.capacity + self.values.len() } pub fn push(&mut self, value: T) -> usize { @@ -89,7 +87,7 @@ impl UniformVec { } fn reserve_buffer(&mut self, capacity: usize, device: &RenderDevice) -> bool { - if capacity > self.capacity { + if capacity > self.scratch.len() { self.capacity = capacity; let size = Self::ITEM_SIZE * capacity; self.scratch.resize(size, 0); From 0a45b6d1b533540009c47cb81e466f4450c4703f Mon Sep 17 00:00:00 2001 From: james7132 Date: Wed, 2 Mar 2022 12:47:52 -0800 Subject: [PATCH 08/13] Fix build and address review comments --- crates/bevy_pbr/src/render/light.rs | 2 +- crates/bevy_render/src/render_component.rs | 2 +- .../src/render_resource/buffer_vec.rs | 17 ++++++++++--- .../src/render_resource/uniform_vec.rs | 25 +++++++++++-------- crates/bevy_render/src/view/mod.rs | 2 +- 5 files changed, 30 insertions(+), 18 deletions(-) diff --git a/crates/bevy_pbr/src/render/light.rs b/crates/bevy_pbr/src/render/light.rs index cafde310e598d..1181936c3a44a 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -867,7 +867,7 @@ pub fn prepare_lights( lights: view_lights, }, ViewLightsUniformOffset { - offset: light_meta.view_gpu_lights.push(gpu_lights), + offset: light_meta.view_gpu_lights.push_and_get_offset(gpu_lights), }, )); } diff --git a/crates/bevy_render/src/render_component.rs b/crates/bevy_render/src/render_component.rs index 1c72786f89f16..ceda8fdbb2e44 100644 --- a/crates/bevy_render/src/render_component.rs +++ b/crates/bevy_render/src/render_component.rs @@ -115,7 +115,7 @@ fn prepare_uniform_components( commands .get_or_spawn(entity) .insert(DynamicUniformIndex:: { - index: component_uniforms.uniforms.push(component.clone()), + index: component_uniforms.uniforms.push_and_get_offset(component.clone()), marker: PhantomData, }); } diff --git a/crates/bevy_render/src/render_resource/buffer_vec.rs b/crates/bevy_render/src/render_resource/buffer_vec.rs index 3f3e59979d802..03c448b7221db 100644 --- a/crates/bevy_render/src/render_resource/buffer_vec.rs +++ b/crates/bevy_render/src/render_resource/buffer_vec.rs @@ -29,7 +29,7 @@ impl Default for BufferVec { impl BufferVec { /// Creates a new [`BufferVec`] with the associated [`BufferUsages`]. /// - /// This does not immediately allocate a buffer. + /// This does not immediately allocate a system/video RAM buffers. pub fn new(buffer_usage: BufferUsages) -> Self { Self { buffer_usage, @@ -43,6 +43,12 @@ impl BufferVec { self.buffer.as_ref() } + /// Gets the capacity of the underlying buffer, returning 0 if it hasn't been allocated. + #[inline] + pub fn buffer_capacity(&self) -> usize { + self.capacity + } + /// Queues up a copy of the contents of the [`BufferVec`] into the underlying /// buffer. /// @@ -54,7 +60,7 @@ impl BufferVec { } self.reserve_buffer(self.values.len(), device); if let Some(buffer) = &self.buffer { - let range = 0..std::mem::size_of::() * self.values.len(); + let range = 0..self.size(); let bytes: &[u8] = cast_slice(&self.values); queue.write_buffer(buffer, 0, &bytes[range]); } @@ -63,15 +69,18 @@ impl BufferVec { fn reserve_buffer(&mut self, capacity: usize, device: &RenderDevice) { if capacity > self.capacity { self.capacity = capacity; - let size = std::mem::size_of::() * capacity; self.buffer = Some(device.create_buffer(&wgpu::BufferDescriptor { label: None, - size: size as wgpu::BufferAddress, + size: self.size() as wgpu::BufferAddress, usage: BufferUsages::COPY_DST | self.buffer_usage, mapped_at_creation: false, })); } } + + fn size(&self) -> usize { + std::mem::size_of::() * self.capacity + } } impl Deref for BufferVec { diff --git a/crates/bevy_render/src/render_resource/uniform_vec.rs b/crates/bevy_render/src/render_resource/uniform_vec.rs index fb921bb513360..52eb3527cf731 100644 --- a/crates/bevy_render/src/render_resource/uniform_vec.rs +++ b/crates/bevy_render/src/render_resource/uniform_vec.rs @@ -62,7 +62,7 @@ impl UniformVec { self.values.len() } - pub fn push(&mut self, value: T) -> usize { + pub fn push_and_get_offset(&mut self, value: T) -> usize { let index = self.values.len(); self.values.push(value); index @@ -77,23 +77,21 @@ impl UniformVec { if self.values.is_empty() { return; } - self.reserve_buffer(self.values.len(), device); + self.reserve_buffer(device); if let Some(uniform_buffer) = &self.uniform_buffer { - let range = 0..Self::ITEM_SIZE * self.values.len(); + let range = 0..self.size(); let mut writer = std140::Writer::new(&mut self.scratch[range.clone()]); writer.write(self.values.as_slice()).unwrap(); queue.write_buffer(uniform_buffer, 0, &self.scratch[range]); } } - fn reserve_buffer(&mut self, capacity: usize, device: &RenderDevice) -> bool { - if capacity > self.scratch.len() { - self.capacity = capacity; - let size = Self::ITEM_SIZE * capacity; - self.scratch.resize(size, 0); + fn reserve_buffer(&mut self, device: &RenderDevice) -> bool { + if self.size() > self.scratch.len() { + self.scratch.resize(self.size(), 0); self.uniform_buffer = Some(device.create_buffer(&BufferDescriptor { label: None, - size: size as wgpu::BufferAddress, + size: self.size() as wgpu::BufferAddress, usage: BufferUsages::COPY_DST | BufferUsages::UNIFORM, mapped_at_creation: false, })); @@ -102,6 +100,10 @@ impl UniformVec { false } } + + fn size(&self) -> usize { + Self::ITEM_SIZE * self.values.len() + } } impl Deref for UniformVec { @@ -160,8 +162,9 @@ impl DynamicUniformVec { } #[inline] - pub fn push(&mut self, value: T) -> u32 { - (self.uniform_vec.push(DynamicUniform(value)) * UniformVec::>::ITEM_SIZE) + pub fn push_and_get_offset(&mut self, value: T) -> u32 { + (self.uniform_vec.push_and_get_offset(DynamicUniform(value)) * + UniformVec::>::ITEM_SIZE) as u32 } diff --git a/crates/bevy_render/src/view/mod.rs b/crates/bevy_render/src/view/mod.rs index 95233083c6f6c..49cda4b966fec 100644 --- a/crates/bevy_render/src/view/mod.rs +++ b/crates/bevy_render/src/view/mod.rs @@ -151,7 +151,7 @@ fn prepare_view_uniforms( let view = camera.transform.compute_matrix(); let inverse_view = view.inverse(); let view_uniforms = ViewUniformOffset { - offset: view_uniforms.uniforms.push(ViewUniform { + offset: view_uniforms.uniforms.push_and_get_offset(ViewUniform { view_proj: projection * inverse_view, view, inverse_view, From 2fea3ecb2103f6ace100b8198cb9dbaef7b341b0 Mon Sep 17 00:00:00 2001 From: james7132 Date: Wed, 2 Mar 2022 12:51:28 -0800 Subject: [PATCH 09/13] Formatting and DynamicUniformVec Deref(Mut) --- crates/bevy_render/src/render_component.rs | 4 ++- .../src/render_resource/buffer_vec.rs | 2 +- .../src/render_resource/uniform_vec.rs | 28 ++++++++++--------- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/crates/bevy_render/src/render_component.rs b/crates/bevy_render/src/render_component.rs index ceda8fdbb2e44..4530d464b0a24 100644 --- a/crates/bevy_render/src/render_component.rs +++ b/crates/bevy_render/src/render_component.rs @@ -115,7 +115,9 @@ fn prepare_uniform_components( commands .get_or_spawn(entity) .insert(DynamicUniformIndex:: { - index: component_uniforms.uniforms.push_and_get_offset(component.clone()), + index: component_uniforms + .uniforms + .push_and_get_offset(component.clone()), marker: PhantomData, }); } diff --git a/crates/bevy_render/src/render_resource/buffer_vec.rs b/crates/bevy_render/src/render_resource/buffer_vec.rs index 03c448b7221db..e0a6cf0a8c2a9 100644 --- a/crates/bevy_render/src/render_resource/buffer_vec.rs +++ b/crates/bevy_render/src/render_resource/buffer_vec.rs @@ -77,7 +77,7 @@ impl BufferVec { })); } } - + fn size(&self) -> usize { std::mem::size_of::() * self.capacity } diff --git a/crates/bevy_render/src/render_resource/uniform_vec.rs b/crates/bevy_render/src/render_resource/uniform_vec.rs index 52eb3527cf731..9188ee1310745 100644 --- a/crates/bevy_render/src/render_resource/uniform_vec.rs +++ b/crates/bevy_render/src/render_resource/uniform_vec.rs @@ -145,16 +145,6 @@ impl DynamicUniformVec { self.uniform_vec.binding() } - #[inline] - pub fn len(&self) -> usize { - self.uniform_vec.len() - } - - #[inline] - pub fn is_empty(&self) -> bool { - self.uniform_vec.is_empty() - } - /// Gets the capacity of the underlying buffer, in bytes. #[inline] pub fn buffer_capacity(&self) -> usize { @@ -163,9 +153,8 @@ impl DynamicUniformVec { #[inline] pub fn push_and_get_offset(&mut self, value: T) -> u32 { - (self.uniform_vec.push_and_get_offset(DynamicUniform(value)) * - UniformVec::>::ITEM_SIZE) - as u32 + (self.uniform_vec.push_and_get_offset(DynamicUniform(value)) + * UniformVec::>::ITEM_SIZE) as u32 } /// Queues up a copy of the contents of the [`UniformVec`] into the underlying @@ -183,3 +172,16 @@ impl DynamicUniformVec { self.uniform_vec.clear(); } } + +impl Deref for DynamicUniformVec { + type Target = Vec>; + fn deref(&self) -> &Self::Target { + &self.uniform_vec + } +} + +impl DerefMut for DynamicUniformVec { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.uniform_vec + } +} From ffc1fce24ddca57f451cfd4db51d49060bde22fb Mon Sep 17 00:00:00 2001 From: james7132 Date: Wed, 2 Mar 2022 13:02:58 -0800 Subject: [PATCH 10/13] Add functions for extracting parts of the *BufferVec --- .../src/render_resource/buffer_vec.rs | 12 +++++++++ .../src/render_resource/uniform_vec.rs | 25 ++++++++++++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/crates/bevy_render/src/render_resource/buffer_vec.rs b/crates/bevy_render/src/render_resource/buffer_vec.rs index e0a6cf0a8c2a9..b26032ba38cce 100644 --- a/crates/bevy_render/src/render_resource/buffer_vec.rs +++ b/crates/bevy_render/src/render_resource/buffer_vec.rs @@ -66,6 +66,18 @@ impl BufferVec { } } + /// Consumes the [`BufferVec`] and returns the underlying [`Vec`]. + /// If a buffer was allocated, it will be dropped. + pub fn take_vec(self) -> Vec { + self.values + } + + /// Consumes the [`BufferVec`] and returns the underlying [`Buffer`] + /// if one was allocated. + pub fn take_buffer(self) -> Option { + self.buffer + } + fn reserve_buffer(&mut self, capacity: usize, device: &RenderDevice) { if capacity > self.capacity { self.capacity = capacity; diff --git a/crates/bevy_render/src/render_resource/uniform_vec.rs b/crates/bevy_render/src/render_resource/uniform_vec.rs index 9188ee1310745..137b1d207bd04 100644 --- a/crates/bevy_render/src/render_resource/uniform_vec.rs +++ b/crates/bevy_render/src/render_resource/uniform_vec.rs @@ -86,6 +86,18 @@ impl UniformVec { } } + /// Consumes the [`UniformBufferVec`] and returns the underlying [`Vec`]. + /// If a buffer was allocated, it will be dropped. + pub fn take_vec(self) -> Vec { + self.values + } + + /// Consumes the [`UniformBufferVec`] and returns the underlying [`Buffer`] + /// if one was allocated. + pub fn take_buffer(self) -> Option { + self.uniform_buffer + } + fn reserve_buffer(&mut self, device: &RenderDevice) -> bool { if self.size() > self.scratch.len() { self.scratch.resize(self.size(), 0); @@ -167,9 +179,16 @@ impl DynamicUniformVec { self.uniform_vec.write_buffer(device, queue); } - #[inline] - pub fn clear(&mut self) { - self.uniform_vec.clear(); + /// Consumes the [`DynamicUniformBufferVec`] and returns the underlying [`Vec`]. + /// If a buffer was allocated, it will be dropped. + pub fn take_vec(self) -> Vec> { + self.uniform_vec.take_vec() + } + + /// Consumes the [`DynamicUniformBufferVec`] and returns the underlying [`Buffer`] + /// if one was allocated. + pub fn take_buffer(self) -> Option { + self.uniform_vec.take_buffer() } } From 4218d70bf24fa94f04f347a560a5adf40155be77 Mon Sep 17 00:00:00 2001 From: james7132 Date: Thu, 3 Mar 2022 11:44:03 -0800 Subject: [PATCH 11/13] fix panic on reserve --- crates/bevy_render/src/render_resource/buffer_vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_render/src/render_resource/buffer_vec.rs b/crates/bevy_render/src/render_resource/buffer_vec.rs index b26032ba38cce..fc1bb45a0f16b 100644 --- a/crates/bevy_render/src/render_resource/buffer_vec.rs +++ b/crates/bevy_render/src/render_resource/buffer_vec.rs @@ -91,7 +91,7 @@ impl BufferVec { } fn size(&self) -> usize { - std::mem::size_of::() * self.capacity + std::mem::size_of::() * self.values.len() } } From 118a4adf287bd97ad36c3faf79a25d48a6261b01 Mon Sep 17 00:00:00 2001 From: james7132 Date: Thu, 3 Mar 2022 15:36:26 -0800 Subject: [PATCH 12/13] Address review comments --- .../src/render_resource/buffer_vec.rs | 6 ------ .../src/render_resource/uniform_vec.rs | 19 +++---------------- 2 files changed, 3 insertions(+), 22 deletions(-) diff --git a/crates/bevy_render/src/render_resource/buffer_vec.rs b/crates/bevy_render/src/render_resource/buffer_vec.rs index fc1bb45a0f16b..40bef82aab832 100644 --- a/crates/bevy_render/src/render_resource/buffer_vec.rs +++ b/crates/bevy_render/src/render_resource/buffer_vec.rs @@ -43,12 +43,6 @@ impl BufferVec { self.buffer.as_ref() } - /// Gets the capacity of the underlying buffer, returning 0 if it hasn't been allocated. - #[inline] - pub fn buffer_capacity(&self) -> usize { - self.capacity - } - /// Queues up a copy of the contents of the [`BufferVec`] into the underlying /// buffer. /// diff --git a/crates/bevy_render/src/render_resource/uniform_vec.rs b/crates/bevy_render/src/render_resource/uniform_vec.rs index 137b1d207bd04..5b27a466d1eb2 100644 --- a/crates/bevy_render/src/render_resource/uniform_vec.rs +++ b/crates/bevy_render/src/render_resource/uniform_vec.rs @@ -54,14 +54,6 @@ impl UniformVec { })) } - /// Gets the capacity of the underlying buffer. - /// - /// Will return 0 if no buffer has been allocated yet. - #[inline] - pub fn buffer_capacity(&self) -> usize { - self.values.len() - } - pub fn push_and_get_offset(&mut self, value: T) -> usize { let index = self.values.len(); self.values.push(value); @@ -99,11 +91,12 @@ impl UniformVec { } fn reserve_buffer(&mut self, device: &RenderDevice) -> bool { - if self.size() > self.scratch.len() { + let size = self.size(); + if size > self.scratch.len() { self.scratch.resize(self.size(), 0); self.uniform_buffer = Some(device.create_buffer(&BufferDescriptor { label: None, - size: self.size() as wgpu::BufferAddress, + size: size as wgpu::BufferAddress, usage: BufferUsages::COPY_DST | BufferUsages::UNIFORM, mapped_at_creation: false, })); @@ -157,12 +150,6 @@ impl DynamicUniformVec { self.uniform_vec.binding() } - /// Gets the capacity of the underlying buffer, in bytes. - #[inline] - pub fn buffer_capacity(&self) -> usize { - self.uniform_vec.buffer_capacity() - } - #[inline] pub fn push_and_get_offset(&mut self, value: T) -> u32 { (self.uniform_vec.push_and_get_offset(DynamicUniform(value)) From 3951665134c85380c35f06c206a8619c99cbd8c9 Mon Sep 17 00:00:00 2001 From: james7132 Date: Thu, 3 Mar 2022 15:38:09 -0800 Subject: [PATCH 13/13] fix docs --- crates/bevy_render/src/render_resource/uniform_vec.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/bevy_render/src/render_resource/uniform_vec.rs b/crates/bevy_render/src/render_resource/uniform_vec.rs index 5b27a466d1eb2..0b210362ae4f4 100644 --- a/crates/bevy_render/src/render_resource/uniform_vec.rs +++ b/crates/bevy_render/src/render_resource/uniform_vec.rs @@ -78,13 +78,13 @@ impl UniformVec { } } - /// Consumes the [`UniformBufferVec`] and returns the underlying [`Vec`]. + /// Consumes the [`UniformVec`] and returns the underlying [`Vec`]. /// If a buffer was allocated, it will be dropped. pub fn take_vec(self) -> Vec { self.values } - /// Consumes the [`UniformBufferVec`] and returns the underlying [`Buffer`] + /// Consumes the [`UniformVec`] and returns the underlying [`Buffer`] /// if one was allocated. pub fn take_buffer(self) -> Option { self.uniform_buffer @@ -166,13 +166,13 @@ impl DynamicUniformVec { self.uniform_vec.write_buffer(device, queue); } - /// Consumes the [`DynamicUniformBufferVec`] and returns the underlying [`Vec`]. + /// Consumes the [`DynamicUniformVec`] and returns the underlying [`Vec`]. /// If a buffer was allocated, it will be dropped. pub fn take_vec(self) -> Vec> { self.uniform_vec.take_vec() } - /// Consumes the [`DynamicUniformBufferVec`] and returns the underlying [`Buffer`] + /// Consumes the [`DynamicUniformVec`] and returns the underlying [`Buffer`] /// if one was allocated. pub fn take_buffer(self) -> Option { self.uniform_vec.take_buffer()