Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 31 additions & 9 deletions fidget-wgpu/src/buf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
//!
//! This module is mostly internal to the crate, but is public because its types
//! appear as return values and arguments.
use crate::Gpu;
use fidget_core::render::{ImageSize, VoxelSize};
use fidget_raster::RenderSize;
use zerocopy::FromBytes;
use zerocopy::{FromBytes, IntoBytes};

/// Handle around a growable GPU buffer
///
Expand Down Expand Up @@ -148,23 +149,44 @@ pub(crate) type FlexConfigBuffer<C, T> = FlexBuffer<FlexConfigTag<C, T>>;

impl<C, T> FlexConfigBuffer<C, T>
where
C: zerocopy::IntoBytes + zerocopy::Immutable + Copy,
T: Copy,
C: zerocopy::IntoBytes + zerocopy::Immutable,
T: zerocopy::IntoBytes + zerocopy::Immutable + Copy,
{
/// Writes a config value to the buffer
pub(crate) fn write_config(&self, c: &C, queue: &wgpu::Queue) {
pub(crate) fn write(
&mut self,
gpu: &Gpu,
c: &C,
data: &[T],
) -> Result<ConfigBufferWrite, BufferSizeError> {
let r = self.grow_to_fit(&gpu.device, data.len().into())?;
let config_len = std::mem::size_of::<C>();
let mut writer = queue
let data_len = std::mem::size_of_val(data);
let mut writer = gpu
.queue
.write_buffer_with(
self.data(),
&self.data,
0,
(config_len as u64).try_into().unwrap(),
((config_len + data_len) as u64).try_into().unwrap(),
)
.unwrap();
writer.copy_from_slice(c.as_bytes());
writer.slice(..config_len).copy_from_slice(c.as_bytes());
writer.slice(config_len..).copy_from_slice(data.as_bytes());
Ok(match r {
std::cmp::Ordering::Equal => ConfigBufferWrite::BufferUnchanged,
std::cmp::Ordering::Less | std::cmp::Ordering::Greater => {
ConfigBufferWrite::BufferChanged
}
})
}
}

#[derive(Copy, Clone, Debug)]
#[must_use]
pub(crate) enum ConfigBufferWrite {
BufferChanged,
BufferUnchanged,
}

impl<T: BufferTag> FlexBuffer<T> {
pub(crate) fn new(
device: &wgpu::Device,
Expand Down
33 changes: 8 additions & 25 deletions fidget-wgpu/src/color.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
//! [`voxel::effects::ColorWorkspace`](crate::voxel::effects::ColorWorkspace)
use crate::{
CopyVarsChanged, CopyVarsError, Gpu,
buf::{BufferSizeError, FlexBuffer, FlexConfigBuffer},
buf::{BufferSizeError, ConfigBufferWrite, FlexBuffer, FlexConfigBuffer},
tag,
voxel::VarsBufferTag,
};
Expand Down Expand Up @@ -101,31 +101,18 @@ where
Ok(())
}

pub(crate) fn copy_tape(
pub(crate) fn copy_config_and_tape(
&mut self,
gpu: &Gpu,
config: &C,
bytecode: &[u32],
) -> Result<(), BufferSizeError> {
let r = self
.config
.grow_to_fit(&gpu.device, bytecode.len().into())?;
if !matches!(r, std::cmp::Ordering::Equal) {
self.bind_group = Default::default();
match self.config.write(gpu, config, bytecode)? {
ConfigBufferWrite::BufferChanged => {
self.bind_group = Default::default()
}
ConfigBufferWrite::BufferUnchanged => (),
}
let Ok(byte_count) =
(std::mem::size_of_val(bytecode) as u64).try_into()
else {
return Ok(());
};
let mut writer = gpu
.queue
.write_buffer_with(
self.config.data(),
std::mem::size_of::<C>() as u64,
byte_count,
)
.unwrap();
writer.copy_from_slice(bytecode.as_bytes());
Ok(())
}

Expand All @@ -152,10 +139,6 @@ where
writer.copy_from_slice(shape_starts.as_bytes());
Ok(())
}

pub(crate) fn copy_config(&mut self, gpu: &Gpu, config: &C) {
self.config.write_config(config, &gpu.queue)
}
}

/// Error type when constructing a [`ShapeColorBuffers`]
Expand Down
13 changes: 4 additions & 9 deletions fidget-wgpu/src/pixel/effects/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -527,14 +527,6 @@ impl ColorContext {
CopyVarsError::BufferSize(b) => ColorError::VarBufferSize(b),
CopyVarsError::MissingVar(v) => ColorError::MissingVar(v),
})?;

bufs.copy_tape(gpu, shape.bytecode())
.map_err(ColorError::ConfigBufferSize)?;
bufs.copy_shape_starts(gpu, shape.shape_start())
.expect("shape starts should always fit if shape bytecode fits");

// We'll write the config last, because writing the tape could have
// invalidated it.
let config = ColorConfig {
mat: mat4.data.as_slice().try_into().unwrap(),
axes: shape.axes(),
Expand All @@ -543,7 +535,10 @@ impl ColorContext {
_pad: [0; 3],
z: settings.z,
};
bufs.copy_config(gpu, &config);
bufs.copy_config_and_tape(gpu, &config, shape.bytecode())
.map_err(ColorError::ConfigBufferSize)?;
bufs.copy_shape_starts(gpu, shape.shape_start())
.expect("shape starts should always fit if shape bytecode fits");

let config_bg =
bufs.config_bind_group(&gpu.device, &self.config_bind_group_layout);
Expand Down
12 changes: 4 additions & 8 deletions fidget-wgpu/src/voxel/effects/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1306,20 +1306,16 @@ impl ColorContext {
CopyVarsError::BufferSize(b) => ColorError::VarBufferSize(b),
CopyVarsError::MissingVar(v) => ColorError::MissingVar(v),
})?;
bufs.copy_tape(gpu, shape.bytecode())
.map_err(ColorError::ConfigBufferSize)?;
bufs.copy_shape_starts(gpu, shape.shape_start())
.expect("shape starts should always fit if shape bytecode fits");

// We'll write the config last, because writing the tape could have
// invalidated it.
let config = ColorConfig {
mat: mat.data.as_slice().try_into().unwrap(),
axes: shape.axes(),
image_size: [size.width(), size.height()],
_pad: 0,
};
bufs.copy_config(gpu, &config);
bufs.copy_config_and_tape(gpu, &config, shape.bytecode())
.map_err(ColorError::ConfigBufferSize)?;
bufs.copy_shape_starts(gpu, shape.shape_start())
.expect("shape starts should always fit if shape bytecode fits");

let config_bg =
bufs.config_bind_group(&gpu.device, &self.config_bind_group_layout);
Expand Down