From b8c1809ea101cece6943432fd3597f785c39af09 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 7 Feb 2023 23:55:16 +0100 Subject: Refactor `triangle::Pipeline` into `prepare` and `render` architecture And get rid of the staging belt! :tada: --- wgpu/src/buffer/dynamic.rs | 23 +++-------------------- wgpu/src/buffer/static.rs | 21 ++++----------------- 2 files changed, 7 insertions(+), 37 deletions(-) (limited to 'wgpu/src/buffer') diff --git a/wgpu/src/buffer/dynamic.rs b/wgpu/src/buffer/dynamic.rs index 88289b98..43fc47ac 100644 --- a/wgpu/src/buffer/dynamic.rs +++ b/wgpu/src/buffer/dynamic.rs @@ -112,25 +112,8 @@ impl Buffer { } /// Write the contents of this dynamic buffer to the GPU via staging belt command. - pub fn write( - &mut self, - device: &wgpu::Device, - staging_belt: &mut wgpu::util::StagingBelt, - encoder: &mut wgpu::CommandEncoder, - ) { - let size = self.cpu.get_ref().len(); - - if let Some(buffer_size) = wgpu::BufferSize::new(size as u64) { - let mut buffer = staging_belt.write_buffer( - encoder, - &self.gpu, - 0, - buffer_size, - device, - ); - - buffer.copy_from_slice(self.cpu.get_ref()); - } + pub fn write(&mut self, queue: &wgpu::Queue) { + queue.write_buffer(&self.gpu, 0, self.cpu.get_ref()); } // Gets the aligned offset at the given index from the CPU buffer. @@ -184,7 +167,7 @@ impl Internal { } /// Returns bytearray of aligned CPU buffer. - pub(super) fn get_ref(&self) -> &Vec { + pub(super) fn get_ref(&self) -> &[u8] { match self { Internal::Uniform(buf) => buf.as_ref(), #[cfg(not(target_arch = "wasm32"))] diff --git a/wgpu/src/buffer/static.rs b/wgpu/src/buffer/static.rs index ef87422f..7ae7edd2 100644 --- a/wgpu/src/buffer/static.rs +++ b/wgpu/src/buffer/static.rs @@ -3,7 +3,7 @@ use std::marker::PhantomData; use std::mem; //128 triangles/indices -const DEFAULT_STATIC_BUFFER_COUNT: wgpu::BufferAddress = 128; +const DEFAULT_STATIC_BUFFER_COUNT: wgpu::BufferAddress = 1_000; /// A generic buffer struct useful for items which have no alignment requirements /// (e.g. Vertex, Index buffers) & no dynamic offsets. @@ -71,28 +71,15 @@ impl Buffer { /// Returns the size of the written bytes. pub fn write( &mut self, - device: &wgpu::Device, - staging_belt: &mut wgpu::util::StagingBelt, - encoder: &mut wgpu::CommandEncoder, + queue: &wgpu::Queue, offset: u64, content: &[T], ) -> u64 { let bytes = bytemuck::cast_slice(content); let bytes_size = bytes.len() as u64; - if let Some(buffer_size) = wgpu::BufferSize::new(bytes_size) { - let mut buffer = staging_belt.write_buffer( - encoder, - &self.gpu, - offset, - buffer_size, - device, - ); - - buffer.copy_from_slice(bytes); - - self.offsets.push(offset); - } + queue.write_buffer(&self.gpu, offset, bytes); + self.offsets.push(offset); bytes_size } -- cgit From 2097a56b58d8fe1784a625f69c1cdd38fcfb9a52 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 9 Feb 2023 06:54:51 +0100 Subject: Provide some margin to static buffers when growing --- wgpu/src/buffer/static.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'wgpu/src/buffer') diff --git a/wgpu/src/buffer/static.rs b/wgpu/src/buffer/static.rs index 7ae7edd2..d8ae116e 100644 --- a/wgpu/src/buffer/static.rs +++ b/wgpu/src/buffer/static.rs @@ -2,8 +2,7 @@ use bytemuck::{Pod, Zeroable}; use std::marker::PhantomData; use std::mem; -//128 triangles/indices -const DEFAULT_STATIC_BUFFER_COUNT: wgpu::BufferAddress = 1_000; +const DEFAULT_COUNT: wgpu::BufferAddress = 128; /// A generic buffer struct useful for items which have no alignment requirements /// (e.g. Vertex, Index buffers) & no dynamic offsets. @@ -25,7 +24,7 @@ impl Buffer { label: &'static str, usages: wgpu::BufferUsages, ) -> Self { - let size = (mem::size_of::() as u64) * DEFAULT_STATIC_BUFFER_COUNT; + let size = (mem::size_of::() as u64) * DEFAULT_COUNT; Self { offsets: Vec::new(), @@ -57,9 +56,13 @@ impl Buffer { let size = (mem::size_of::() * new_count) as u64; if self.size < size { + self.size = + (mem::size_of::() * (new_count + new_count / 2)) as u64; + + self.gpu = + Self::gpu_buffer(device, self.label, self.size, self.usages); + self.offsets.clear(); - self.size = size; - self.gpu = Self::gpu_buffer(device, self.label, size, self.usages); true } else { false -- cgit From 6551a0b2ab6c831dd1d3646ecf55180339275e22 Mon Sep 17 00:00:00 2001 From: Bingus Date: Thu, 11 May 2023 09:12:06 -0700 Subject: Added support for gradients as background variants + other optimizations. --- wgpu/src/buffer/dynamic.rs | 202 --------------------------------------------- wgpu/src/buffer/static.rs | 107 ------------------------ 2 files changed, 309 deletions(-) delete mode 100644 wgpu/src/buffer/dynamic.rs delete mode 100644 wgpu/src/buffer/static.rs (limited to 'wgpu/src/buffer') diff --git a/wgpu/src/buffer/dynamic.rs b/wgpu/src/buffer/dynamic.rs deleted file mode 100644 index 43fc47ac..00000000 --- a/wgpu/src/buffer/dynamic.rs +++ /dev/null @@ -1,202 +0,0 @@ -//! Utilities for uniform buffer operations. -use encase::private::WriteInto; -use encase::ShaderType; - -use std::fmt; -use std::marker::PhantomData; - -/// A dynamic buffer is any type of buffer which does not have a static offset. -#[derive(Debug)] -pub struct Buffer { - offsets: Vec, - cpu: Internal, - gpu: wgpu::Buffer, - label: &'static str, - size: u64, - _data: PhantomData, -} - -impl Buffer { - /// Creates a new dynamic uniform buffer. - pub fn uniform(device: &wgpu::Device, label: &'static str) -> Self { - Buffer::new( - device, - Internal::Uniform(encase::DynamicUniformBuffer::new(Vec::new())), - label, - wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, - ) - } - - #[cfg(not(target_arch = "wasm32"))] - /// Creates a new dynamic storage buffer. - pub fn storage(device: &wgpu::Device, label: &'static str) -> Self { - Buffer::new( - device, - Internal::Storage(encase::DynamicStorageBuffer::new(Vec::new())), - label, - wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST, - ) - } - - fn new( - device: &wgpu::Device, - dynamic_buffer_type: Internal, - label: &'static str, - usage: wgpu::BufferUsages, - ) -> Self { - let initial_size = u64::from(T::min_size()); - - Self { - offsets: Vec::new(), - cpu: dynamic_buffer_type, - gpu: Buffer::::create_gpu_buffer( - device, - label, - usage, - initial_size, - ), - label, - size: initial_size, - _data: Default::default(), - } - } - - fn create_gpu_buffer( - device: &wgpu::Device, - label: &'static str, - usage: wgpu::BufferUsages, - size: u64, - ) -> wgpu::Buffer { - device.create_buffer(&wgpu::BufferDescriptor { - label: Some(label), - size, - usage, - mapped_at_creation: false, - }) - } - - /// Write a new value to the CPU buffer with proper alignment. Stores the returned offset value - /// in the buffer for future use. - pub fn push(&mut self, value: &T) { - //this write operation on the cpu buffer will adjust for uniform alignment requirements - let offset = self.cpu.write(value); - self.offsets.push(offset); - } - - /// Resize buffer contents if necessary. This will re-create the GPU buffer if current size is - /// less than the newly computed size from the CPU buffer. - /// - /// If the gpu buffer is resized, its bind group will need to be recreated! - pub fn resize(&mut self, device: &wgpu::Device) -> bool { - let new_size = self.cpu.get_ref().len() as u64; - - if self.size < new_size { - let usages = match self.cpu { - Internal::Uniform(_) => { - wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST - } - #[cfg(not(target_arch = "wasm32"))] - Internal::Storage(_) => { - wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST - } - }; - - self.gpu = Buffer::::create_gpu_buffer( - device, self.label, usages, new_size, - ); - self.size = new_size; - true - } else { - false - } - } - - /// Write the contents of this dynamic buffer to the GPU via staging belt command. - pub fn write(&mut self, queue: &wgpu::Queue) { - queue.write_buffer(&self.gpu, 0, self.cpu.get_ref()); - } - - // Gets the aligned offset at the given index from the CPU buffer. - pub fn offset_at_index(&self, index: usize) -> wgpu::DynamicOffset { - let offset = self - .offsets - .get(index) - .copied() - .expect("Index not found in offsets."); - - offset - } - - /// Returns a reference to the GPU buffer. - pub fn raw(&self) -> &wgpu::Buffer { - &self.gpu - } - - /// Reset the buffer. - pub fn clear(&mut self) { - self.offsets.clear(); - self.cpu.clear(); - } -} - -// Currently supported dynamic buffers. -enum Internal { - Uniform(encase::DynamicUniformBuffer>), - #[cfg(not(target_arch = "wasm32"))] - //storage buffers are not supported on wgpu wasm target (yet) - Storage(encase::DynamicStorageBuffer>), -} - -impl Internal { - /// Writes the current value to its CPU buffer with proper alignment. - pub(super) fn write( - &mut self, - value: &T, - ) -> wgpu::DynamicOffset { - match self { - Internal::Uniform(buf) => buf - .write(value) - .expect("Error when writing to dynamic uniform buffer.") - as u32, - #[cfg(not(target_arch = "wasm32"))] - Internal::Storage(buf) => buf - .write(value) - .expect("Error when writing to dynamic storage buffer.") - as u32, - } - } - - /// Returns bytearray of aligned CPU buffer. - pub(super) fn get_ref(&self) -> &[u8] { - match self { - Internal::Uniform(buf) => buf.as_ref(), - #[cfg(not(target_arch = "wasm32"))] - Internal::Storage(buf) => buf.as_ref(), - } - } - - /// Resets the CPU buffer. - pub(super) fn clear(&mut self) { - match self { - Internal::Uniform(buf) => { - buf.as_mut().clear(); - buf.set_offset(0); - } - #[cfg(not(target_arch = "wasm32"))] - Internal::Storage(buf) => { - buf.as_mut().clear(); - buf.set_offset(0); - } - } - } -} - -impl fmt::Debug for Internal { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Uniform(_) => write!(f, "Internal::Uniform(_)"), - #[cfg(not(target_arch = "wasm32"))] - Self::Storage(_) => write!(f, "Internal::Storage(_)"), - } - } -} diff --git a/wgpu/src/buffer/static.rs b/wgpu/src/buffer/static.rs deleted file mode 100644 index d8ae116e..00000000 --- a/wgpu/src/buffer/static.rs +++ /dev/null @@ -1,107 +0,0 @@ -use bytemuck::{Pod, Zeroable}; -use std::marker::PhantomData; -use std::mem; - -const DEFAULT_COUNT: wgpu::BufferAddress = 128; - -/// A generic buffer struct useful for items which have no alignment requirements -/// (e.g. Vertex, Index buffers) & no dynamic offsets. -#[derive(Debug)] -pub struct Buffer { - //stored sequentially per mesh iteration; refers to the offset index in the GPU buffer - offsets: Vec, - label: &'static str, - usages: wgpu::BufferUsages, - gpu: wgpu::Buffer, - size: wgpu::BufferAddress, - _data: PhantomData, -} - -impl Buffer { - /// Initialize a new static buffer. - pub fn new( - device: &wgpu::Device, - label: &'static str, - usages: wgpu::BufferUsages, - ) -> Self { - let size = (mem::size_of::() as u64) * DEFAULT_COUNT; - - Self { - offsets: Vec::new(), - label, - usages, - gpu: Self::gpu_buffer(device, label, size, usages), - size, - _data: PhantomData, - } - } - - fn gpu_buffer( - device: &wgpu::Device, - label: &'static str, - size: wgpu::BufferAddress, - usage: wgpu::BufferUsages, - ) -> wgpu::Buffer { - device.create_buffer(&wgpu::BufferDescriptor { - label: Some(label), - size, - usage, - mapped_at_creation: false, - }) - } - - /// Returns whether or not the buffer needs to be recreated. This can happen whenever mesh data - /// changes & a redraw is requested. - pub fn resize(&mut self, device: &wgpu::Device, new_count: usize) -> bool { - let size = (mem::size_of::() * new_count) as u64; - - if self.size < size { - self.size = - (mem::size_of::() * (new_count + new_count / 2)) as u64; - - self.gpu = - Self::gpu_buffer(device, self.label, self.size, self.usages); - - self.offsets.clear(); - true - } else { - false - } - } - - /// Writes the current vertex data to the gpu buffer with a memcpy & stores its offset. - /// - /// Returns the size of the written bytes. - pub fn write( - &mut self, - queue: &wgpu::Queue, - offset: u64, - content: &[T], - ) -> u64 { - let bytes = bytemuck::cast_slice(content); - let bytes_size = bytes.len() as u64; - - queue.write_buffer(&self.gpu, offset, bytes); - self.offsets.push(offset); - - bytes_size - } - - fn offset_at(&self, index: usize) -> &wgpu::BufferAddress { - self.offsets - .get(index) - .expect("Offset at index does not exist.") - } - - /// Returns the slice calculated from the offset stored at the given index. - /// e.g. to calculate the slice for the 2nd mesh in the layer, this would be the offset at index - /// 1 that we stored earlier when writing. - pub fn slice_from_index(&self, index: usize) -> wgpu::BufferSlice<'_> { - self.gpu.slice(self.offset_at(index)..) - } - - /// Clears any temporary data from the buffer. - pub fn clear(&mut self) { - self.offsets.clear() - } -} -- cgit