Readjusted namespaces, removed Geometry example as it's no longer relevant.

This commit is contained in:
shan 2022-10-05 10:49:58 -07:00
parent 6e7b3ced0b
commit 30432cbade
27 changed files with 394 additions and 625 deletions

View file

@ -1,3 +1,123 @@
//! Utilities for buffer operations.
pub mod buffer;
pub mod dynamic_buffers;
pub mod dynamic;
use bytemuck::{Pod, Zeroable};
use std::marker::PhantomData;
use std::mem;
//128 triangles/indices
const DEFAULT_STATIC_BUFFER_COUNT: wgpu::BufferAddress = 128;
/// A generic buffer struct useful for items which have no alignment requirements
/// (e.g. Vertex, Index buffers) and are set once and never changed until destroyed.
#[derive(Debug)]
pub(crate) struct StaticBuffer<T> {
//stored sequentially per mesh iteration; refers to the offset index in the GPU buffer
offsets: Vec<wgpu::BufferAddress>,
label: &'static str,
usages: wgpu::BufferUsages,
gpu: wgpu::Buffer,
//the static size of the buffer
size: wgpu::BufferAddress,
_data: PhantomData<T>,
}
impl<T: Pod + Zeroable> StaticBuffer<T> {
/// Initialize a new static buffer.
pub fn new(
device: &wgpu::Device,
label: &'static str,
usages: wgpu::BufferUsages,
) -> Self {
let size = (mem::size_of::<T>() as u64) * DEFAULT_STATIC_BUFFER_COUNT;
Self {
offsets: Vec::new(),
label,
usages,
gpu: Self::gpu_buffer(device, label, size, usages),
size,
_data: Default::default(),
}
}
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 recreate_if_needed(
&mut self,
device: &wgpu::Device,
new_count: usize,
) -> bool {
let size =
wgpu::BufferAddress::from((mem::size_of::<T>() * new_count) as u64);
if self.size <= size {
self.offsets.clear();
self.size = size;
self.gpu = Self::gpu_buffer(device, self.label, size, self.usages);
true
} else {
false
}
}
/// Writes the current vertex data to the gpu buffer if it is currently writable with a memcpy &
/// stores its offset.
///
/// This will return either the offset of the written bytes, or `None` if the GPU buffer is not
/// currently writable.
pub fn write(
&mut self,
device: &wgpu::Device,
staging_belt: &mut wgpu::util::StagingBelt,
encoder: &mut wgpu::CommandEncoder,
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 as u64) {
let mut buffer = staging_belt.write_buffer(
encoder,
&self.gpu,
offset,
buffer_size,
device,
);
buffer.copy_from_slice(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)..)
}
}

View file

@ -1,124 +0,0 @@
//! Utilities for static buffer operations.
use bytemuck::{Pod, Zeroable};
use std::marker::PhantomData;
use std::mem;
//128 triangles/indices
const DEFAULT_STATIC_BUFFER_COUNT: wgpu::BufferAddress = 128;
/// A generic buffer struct useful for items which have no alignment requirements
/// (e.g. Vertex, Index buffers) and are set once and never changed until destroyed.
#[derive(Debug)]
pub(crate) struct StaticBuffer<T> {
//stored sequentially per mesh iteration; refers to the offset index in the GPU buffer
offsets: Vec<wgpu::BufferAddress>,
label: &'static str,
usages: wgpu::BufferUsages,
gpu: wgpu::Buffer,
//the static size of the buffer
size: wgpu::BufferAddress,
_data: PhantomData<T>,
}
impl<T: Pod + Zeroable> StaticBuffer<T> {
/// Initialize a new static buffer.
pub fn new(
device: &wgpu::Device,
label: &'static str,
usages: wgpu::BufferUsages,
) -> Self {
let size = (mem::size_of::<T>() as u64) * DEFAULT_STATIC_BUFFER_COUNT;
Self {
offsets: Vec::new(),
label,
usages,
gpu: Self::gpu_buffer(device, label, size, usages),
size,
_data: Default::default(),
}
}
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 recreate_if_needed(
&mut self,
device: &wgpu::Device,
new_count: usize,
) -> bool {
let size =
wgpu::BufferAddress::from((mem::size_of::<T>() * new_count) as u64);
if self.size <= size {
self.offsets.clear();
self.size = size;
self.gpu = Self::gpu_buffer(device, self.label, size, self.usages);
true
} else {
false
}
}
/// Writes the current vertex data to the gpu buffer if it is currently writable with a memcpy &
/// stores its offset.
///
/// This will return either the offset of the written bytes, or `None` if the GPU buffer is not
/// currently writable.
pub fn write(
&mut self,
device: &wgpu::Device,
staging_belt: &mut wgpu::util::StagingBelt,
encoder: &mut wgpu::CommandEncoder,
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 as u64) {
//offset has to be divisible by 8 for alignment reasons
let actual_offset = if offset % 8 != 0 { offset + 4 } else { offset };
let mut buffer = staging_belt.write_buffer(
encoder,
&self.gpu,
actual_offset,
buffer_size,
device,
);
buffer.copy_from_slice(bytes);
self.offsets.push(actual_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)..)
}
}

View file

@ -4,13 +4,13 @@ use core::fmt;
use std::fmt::Formatter;
use iced_graphics::layer::{attribute_count_of, Mesh};
use iced_graphics::shader::Shader;
use iced_graphics::Size;
use iced_graphics::{layer, Size};
use crate::buffers::buffer::StaticBuffer;
use crate::buffers::StaticBuffer;
use crate::triangle::gradient::GradientPipeline;
use crate::triangle::solid::SolidPipeline;
pub use iced_graphics::triangle::{Mesh2D, Vertex2D};
use layer::mesh;
mod gradient;
mod msaa;
@ -107,7 +107,9 @@ impl Pipeline {
//We are not currently using the return value of these functions as we have no system in
//place to calculate mesh diff, or to know whether or not that would be more performant for
//the majority of use cases. Therefore we will write GPU data every frame (for now).
let _ = self.vertex_buffer.recreate_if_needed(device, total_vertices);
let _ = self
.vertex_buffer
.recreate_if_needed(device, total_vertices);
let _ = self.index_buffer.recreate_if_needed(device, total_indices);
//prepare dynamic buffers & data store for writing
@ -144,11 +146,11 @@ impl Pipeline {
self.index_strides.push(mesh.buffers.indices.len() as u32);
//push uniform data to CPU buffers
match mesh.shader {
Shader::Solid(color) => {
match mesh.style {
mesh::Style::Solid(color) => {
self.pipelines.solid.push(transform, color);
}
Shader::Gradient(gradient) => {
mesh::Style::Gradient(gradient) => {
self.pipelines.gradient.push(transform, gradient);
}
}
@ -204,15 +206,15 @@ impl Pipeline {
clip_bounds.height,
);
match mesh.shader {
Shader::Solid(_) => {
match mesh.style {
mesh::Style::Solid(_) => {
self.pipelines.solid.configure_render_pass(
&mut render_pass,
num_solids,
);
num_solids += 1;
}
Shader::Gradient(_) => {
mesh::Style::Gradient(_) => {
self.pipelines.gradient.configure_render_pass(
&mut render_pass,
num_gradients,

View file

@ -1,4 +1,4 @@
use crate::buffers::dynamic_buffers::DynamicBuffer;
use crate::buffers::dynamic::DynamicBuffer;
use crate::settings;
use crate::triangle::{
default_fragment_target, default_multisample_state,

View file

@ -1,4 +1,4 @@
use crate::buffers::dynamic_buffers::DynamicBuffer;
use crate::buffers::dynamic::DynamicBuffer;
use crate::triangle::{
default_fragment_target, default_multisample_state,
default_triangle_primitive_state, vertex_buffer_layout,