diff --git a/CHANGELOG.md b/CHANGELOG.md
index e9607cb2..4b31f74f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -85,6 +85,8 @@ This section may not be all-inclusive; sorry! I _did_ warn you that
- Similarly, make `ShapeColorBuffers` not store GPU objects, so it can be
constructed independently through `ShapeColorBuffers::new` (and shared between
threads).
+- Rename the workspace buffer objects from `Buffers` to `Workspace` (e.g.
+ `fidget::wgpu::voxel::Buffers`) to more clearly reflect their usage.
# 0.5.0
This is a large release with a bunch of small features, reorganization, and one
diff --git a/demos/cli/src/main.rs b/demos/cli/src/main.rs
index 112af9e1..f507e341 100644
--- a/demos/cli/src/main.rs
+++ b/demos/cli/src/main.rs
@@ -396,11 +396,11 @@ fn run3d_wgpu(
};
let mut image = Default::default();
let start = std::time::Instant::now();
- let mut buffers = ctx.buffers();
- let mut out = gpu.read_buffer_for(buffers.output());
+ let mut workspace = ctx.workspace();
+ let mut out = gpu.read_buffer_for(workspace.output());
let shape = fidget::wgpu::RenderShape::new(&shape)?;
for _ in 0..settings.n {
- image = ctx.run(&shape, &mut buffers, &mut out, cfg)?;
+ image = ctx.run(&shape, &mut workspace, &mut out, cfg)?;
}
let _ = image;
info!(
@@ -410,16 +410,16 @@ fn run3d_wgpu(
);
let effects = fidget::wgpu::voxel::effects::Context::new(&gpu);
- let mut merge_buf = effects.merge_buffers();
- let mut ssao_buf = effects.ssao_buffers();
- let mut shade_buf = effects.shade_buffers();
+ let mut merge_buf = effects.merge_workspace();
+ let mut ssao_buf = effects.ssao_workspace();
+ let mut shade_buf = effects.shade_workspace();
let start = std::time::Instant::now();
use fidget::wgpu::voxel::effects::MergeSettings;
let out_bytes = match mode {
RenderMode3D::Heightmap => {
effects.submit_merge(
- buffers.output(),
+ workspace.output(),
MergeSettings {
denoise: false,
z_scale: zflatten,
@@ -434,7 +434,7 @@ fn run3d_wgpu(
}
RenderMode3D::BlurredOcclusion { denoise } => {
effects.submit_merge(
- buffers.output(),
+ workspace.output(),
MergeSettings {
denoise,
z_scale: zflatten,
@@ -447,7 +447,7 @@ fn run3d_wgpu(
}
RenderMode3D::RawOcclusion { denoise } => {
effects.submit_merge(
- buffers.output(),
+ workspace.output(),
MergeSettings {
denoise,
z_scale: zflatten,
@@ -460,7 +460,7 @@ fn run3d_wgpu(
}
RenderMode3D::Shaded { denoise, ssao } => {
effects.submit_merge(
- buffers.output(),
+ workspace.output(),
MergeSettings {
denoise,
z_scale: zflatten,
@@ -688,7 +688,7 @@ fn run2d_wgpu(
};
let mut image = Default::default();
let start = std::time::Instant::now();
- let mut buffers = ctx.buffers();
+ let mut buffers = ctx.workspace();
let mut out = gpu.read_buffer_for(buffers.output());
let shape = fidget::wgpu::RenderShape::new(&shape)?;
let mut postprocess_time = std::time::Duration::ZERO;
diff --git a/fidget-wgpu/src/lib.rs b/fidget-wgpu/src/lib.rs
index 5e24dc53..10ba0deb 100644
--- a/fidget-wgpu/src/lib.rs
+++ b/fidget-wgpu/src/lib.rs
@@ -1,4 +1,66 @@
//! Shader generation and WGPU-based image rendering
+//!
+//! # API design
+//! Using GPUs is complicated[citation needed]. The APIs in this
+//! crate try to strike a balance between ease of use and efficiency. As
+//! always, feel free to open an issue or discussion if the APIs don't work for
+//! you; they were codesigned along with
+//! [Halfspace](https://github.com/mkeeter/halfspace), and may not yet be
+//! suitable for every use case.
+//!
+//! ## Object types
+//! All of the modules use similar patterns of objects:
+//!
+//! - The [`Gpu`] object is passed around to provide device and queues
+//! - A `Context` object contains pipelines
+//! - A `Workspace` object contains buffers used when rendering
+//! - An output buffer can be read back to the CPU or passed to a subsequent
+//! render pipeline
+//!
+//! ### Context objects
+//! A context object contains GPU pipelines and allow users to dispatch work to
+//! the GPU. Voxel and pixel rendering are managed by [`voxel::Context`] and
+//! [`pixel::Context`] respectively. Post-processing is done by
+//! [`voxel::effects::Context`] and [`pixel::effects::Context`].
+//!
+//! Users are expected to create one (of each) context object per thread or
+//! worker, since GPU resources can't be shared.
+//!
+//! Context objects have two flavors of functions. At the highest level, `run`
+//! and `run_async` functions perform rendering and copy data back to the CPU
+//! (e.g. [`voxel::Context::run`] and [`run_async`](voxel::Context::run_async)).
+//! To simply submit work to the GPU, use a `submit` function (e.g.
+//! [`voxel::Context::submit`]).
+//!
+//! ### Workspace objects
+//! Workspace objects contain all of the buffers that are used when dispatching
+//! work to the GPU. They are also per-thread (or per-worker). You may have
+//! more than one per thread if you want to dispatch multiple jobs
+//! simultaneously; it's your computer.
+//!
+//! Workspaces resize themselves automatically when used in rendering. They
+//! typically have [`size()`](voxel::Workspace::size) (active bytes) and
+//! [`capacity()`](voxel::Workspace::capacity) (total allocated bytes)
+//! functions; users may want to check for overly large ratios and recreate
+//! workspaces.
+//!
+//! Workspaces are stateful; after they are used in a `submit` function, they
+//! will contain data in a GPU buffer. The output buffer is typically accessed
+//! with the `output()` function, e.g. [`voxel::Workspace::output`].
+//!
+//! ### Reading data from buffers
+//! The output of a workspace is a [`FlexBuffer`](crate::buf::FlexBuffer)
+//! (indeed, they are used pervasively throughout this crate). Output buffers
+//! are created with `STORAGE | COPY_SRC`. Reading data back to the CPU is a
+//! three-part process:
+//!
+//! - Create a CPU-readable buffer with [`Gpu::read_buffer_for`]
+//! - Copy data with [`Gpu::copy`]
+//! - Map the readable buffer with [`Gpu::map`] or [`Gpu::map_async`]
+//!
+//! For quick debugging, [`Gpu::read_vec`] does all of these steps. You
+//! wouldn't want to use in a tight loop, since it allocates a GPU buffer on
+//! each call.
#![warn(missing_docs)]
use fidget_bytecode::{Bytecode, ReservedRegister};
diff --git a/fidget-wgpu/src/pixel/effects/mod.rs b/fidget-wgpu/src/pixel/effects/mod.rs
index 92694576..de7b3a20 100644
--- a/fidget-wgpu/src/pixel/effects/mod.rs
+++ b/fidget-wgpu/src/pixel/effects/mod.rs
@@ -12,9 +12,9 @@
//! image to be completed) would simply be blurry; with distance interpolation,
//! it remains sharper (though not pixel-perfect).
//!
-//! Output is stored in the [`MergeBuffers`] object, and may be accessed with
-//! [`output_distance`](MergeBuffers::output_distance) and
-//! [`output_color`](MergeBuffers::output_color).
+//! Output is stored in the [`MergeWorkspace`] object, and may be accessed with
+//! [`output_distance`](MergeWorkspace::output_distance) and
+//! [`output_color`](MergeWorkspace::output_color).
//! Note that if color has not been computed, `output_color` will return `None`.
use crate::{
CopyVarsError, Gpu, RegPipeline,
@@ -97,7 +97,7 @@ tag!(
);
/// Handle to a set of buffers used when merging images
-pub struct MergeBuffers {
+pub struct MergeWorkspace {
config: wgpu::Buffer,
distance: FlexBuffer,
color: FlexBuffer,
@@ -112,7 +112,7 @@ pub struct MergeBuffers {
has_color: bool,
}
-impl MergeBuffers {
+impl MergeWorkspace {
/// Resets the merge buffer
///
/// The next call to [`Context::submit_merge`] will clear the buffer and
@@ -222,14 +222,14 @@ impl Context {
/// Submits a set of merge operations to accumulate a single image
///
- /// [`MergeBuffers::reset`] should be called before the first call to
+ /// [`MergeWorkspace::reset`] should be called before the first call to
/// `submit_merge`. For the first merge after a reset, the output buffer is
/// resized to fit the images; subsequent merges must be of the same size.
pub fn submit_merge(
&self,
image: &FlexBuffer,
remove_nans: bool,
- buf: &mut MergeBuffers,
+ buf: &mut MergeWorkspace,
) -> Result<(), MergeError> {
let size = image.size();
if buf.image_count > 0 {
@@ -320,8 +320,8 @@ impl Context {
Ok(())
}
- /// Builds a new set of [`MergeBuffers`] for the given image size
- pub fn merge_buffers(&self) -> MergeBuffers {
+ /// Builds a new set of [`MergeWorkspace`] for the given image size
+ pub fn merge_workspace(&self) -> MergeWorkspace {
let config = self.gpu.device.create_buffer(&wgpu::BufferDescriptor {
label: Some("config"),
size: std::mem::size_of::() as u64,
@@ -337,7 +337,7 @@ impl Context {
let color =
FlexBuffer::new(&self.gpu.device, "pixel merge color", 64.into())
.unwrap();
- MergeBuffers {
+ MergeWorkspace {
config,
distance,
color,
@@ -348,12 +348,12 @@ impl Context {
/// Submits a color evaluation pass
///
- /// Image size is set from the `MergeBuffers`; the transform matrix is
+ /// Image size is set from the `MergeWorkspace`; the transform matrix is
/// provided separately (but should be the same one used for image
/// evaluation).
pub fn submit_color(
&self,
- merge: &mut MergeBuffers,
+ merge: &mut MergeWorkspace,
settings: ColorSettings,
shape: &ShapeColorBuffers,
bufs: &mut ColorWorkspace,
@@ -369,12 +369,12 @@ impl Context {
/// Submits a color evaluation pass with auxiliary variables
///
- /// Image size is set from the `MergeBuffers`; the transform matrix is
+ /// Image size is set from the `MergeWorkspace`; the transform matrix is
/// provided separately (but should be the same one used for image
/// evaluation).
pub fn submit_color_with_vars(
&self,
- merge: &mut MergeBuffers,
+ merge: &mut MergeWorkspace,
settings: ColorSettings,
shape: &ShapeColorBuffers,
bufs: &mut ColorWorkspace,
@@ -501,7 +501,7 @@ impl ColorContext {
fn submit(
&self,
- image: &mut MergeBuffers,
+ image: &mut MergeWorkspace,
settings: ColorSettings,
shape: &ShapeColorBuffers,
bufs: &mut ColorWorkspace,
diff --git a/fidget-wgpu/src/pixel/mod.rs b/fidget-wgpu/src/pixel/mod.rs
index 887395fc..be3e9eec 100644
--- a/fidget-wgpu/src/pixel/mod.rs
+++ b/fidget-wgpu/src/pixel/mod.rs
@@ -188,12 +188,12 @@ impl RootContext {
fn run(
&self,
ctx: &Context,
- buffers: &Buffers,
+ workspace: &Workspace,
reg_count: u8,
render_size: TileRenderSize,
compute_pass: &mut wgpu::ComputePass,
) {
- let bind_group = buffers.bind_groups.root_tiles(ctx, buffers);
+ let bind_group = workspace.bind_groups.root_tiles(ctx, workspace);
compute_pass.set_pipeline(self.root_pipeline.get(reg_count));
compute_pass.set_bind_group(1, bind_group, &[]);
@@ -265,17 +265,17 @@ impl IntervalTilesContext {
fn run(
&self,
ctx: &Context,
- buffers: &Buffers,
+ workspace: &Workspace,
reg_count: u8,
compute_pass: &mut wgpu::ComputePass,
) {
- let bind_group = buffers.bind_groups.interval_tiles(ctx, buffers);
+ let bind_group = workspace.bind_groups.interval_tiles(ctx, workspace);
compute_pass.set_pipeline(self.tiles_pipeline.get(reg_count));
compute_pass.set_bind_group(1, bind_group, &[]);
// Indirect dispatch based on previous tile output
compute_pass
- .dispatch_workgroups_indirect(buffers.tile64.tiles.data(), 0);
+ .dispatch_workgroups_indirect(workspace.tile64.tiles.data(), 0);
}
}
@@ -340,17 +340,17 @@ impl PixelTilesContext {
fn run(
&self,
ctx: &Context,
- buffers: &Buffers,
+ workspace: &Workspace,
reg_count: u8,
compute_pass: &mut wgpu::ComputePass,
) {
- let bind_group = buffers.bind_groups.pixel_tiles(ctx, buffers);
+ let bind_group = workspace.bind_groups.pixel_tiles(ctx, workspace);
compute_pass.set_pipeline(self.tiles_pipeline.get(reg_count));
compute_pass.set_bind_group(1, bind_group, &[]);
// Indirect dispatch based on previous tile output
compute_pass
- .dispatch_workgroups_indirect(buffers.tile8.tiles.data(), 0);
+ .dispatch_workgroups_indirect(workspace.tile8.tiles.data(), 0);
}
}
@@ -402,11 +402,11 @@ tag!(TileTapesBufferTag, u32, usize, STORAGE | COPY_DST);
tag!(pub PixelBufferTag, RawDistancePixel, ImageSize, STORAGE | COPY_SRC | COPY_DST,
"Tag for a on-GPU buffer storing [`RawDistancePixel`] values");
-/// Buffers for rendering
+/// Workspace for rendering
///
-/// This object is constructed by [`Context::buffers`] and may only be used with
+/// This object is constructed by [`Context::workspace`] and may only be used with
/// that particular [`Context`].
-pub struct Buffers {
+pub struct Workspace {
/// Image render size
///
/// Note that the tile buffers below round up to the nearest root tile
@@ -435,7 +435,7 @@ pub struct Buffers {
bind_groups: BindGroups,
}
-impl Buffers {
+impl Workspace {
/// Builds a new set of buffers with a default size
///
/// It is expected that these will be resized before being used
@@ -514,9 +514,9 @@ impl Buffers {
&mut self,
device: &wgpu::Device,
image_size: ImageSize,
- ) -> Result<(), BuffersError> {
+ ) -> Result<(), BufferError> {
let render_size = TileRenderSize::from(image_size);
- let Buffers {
+ let Workspace {
image_size: image_size_ref,
tile_tapes,
tile64,
@@ -533,25 +533,25 @@ impl Buffers {
*image_size_ref = image_size;
tile_tapes
.grow_to_fit(device, Self::tile_tapes_buf_size(render_size))
- .map_err(|err| BuffersError {
+ .map_err(|err| BufferError {
buf: BufferName::TileTapes,
err,
})?;
tile64
.grow_to_fit(device, render_size)
- .map_err(|e| BuffersError {
+ .map_err(|e| BufferError {
buf: BufferName::Tile64(e.buf),
err: e.err,
})?;
tile8
.grow_to_fit(device, render_size)
- .map_err(|e| BuffersError {
+ .map_err(|e| BufferError {
buf: BufferName::Tile8(e.buf),
err: e.err,
})?;
pixels
.grow_to_fit(device, image_size)
- .map_err(|err| BuffersError {
+ .map_err(|err| BufferError {
buf: BufferName::Pixel,
err,
})?;
@@ -561,7 +561,7 @@ impl Buffers {
/// Returns total allocated size (in bytes)
pub fn capacity(&self) -> u64 {
// Destructure to make sure we take all members into account
- let Buffers {
+ let Workspace {
image_size: _,
config_buf,
vars_buf,
@@ -582,7 +582,7 @@ impl Buffers {
/// Returns total active size (in bytes)
pub fn size(&self) -> u64 {
// Destructure to make sure we take all members into account
- let Buffers {
+ let Workspace {
image_size: _,
vars_buf,
config_buf,
@@ -604,17 +604,17 @@ impl Buffers {
///
/// This is intended for subsequent shaders which want to use the
/// [`RawDistancePixel`] image data without copying to the CPU. It requires
- /// a exclusive borrow of the `Buffers` object (and then extends that
+ /// an exclusive borrow of the `Workspace` object (and then extends that
/// lifetime) so that other callers can't simultaneously touch the buffer.
pub fn output(&mut self) -> &FlexBuffer {
&self.pixels
}
}
-/// Error returned when resizing a [`Buffers`] object
+/// Error returned when resizing buffers in a [`Workspace`] object
#[derive(Debug, thiserror::Error)]
#[error("failed to build {buf} buffer")]
-pub struct BuffersError {
+pub struct BufferError {
/// Buffer which failed to resize
pub buf: BufferName,
/// Error returned by buffer resizing
@@ -660,14 +660,14 @@ pub enum SubmitError {
MissingVar(#[from] MissingVar),
/// Error while resizing buffers
#[error(transparent)]
- Buffers(#[from] BuffersError),
+ Buffers(#[from] BufferError),
}
impl From for SubmitError {
fn from(value: CopyVarsError) -> Self {
match value {
CopyVarsError::MissingVar(v) => Self::MissingVar(v),
- CopyVarsError::BufferSize(err) => Self::Buffers(BuffersError {
+ CopyVarsError::BufferSize(err) => Self::Buffers(BufferError {
buf: BufferName::Vars,
err,
}),
@@ -686,7 +686,7 @@ struct BindGroups {
}
impl BindGroups {
- fn common(&self, ctx: &Context, buffers: &Buffers) -> &wgpu::BindGroup {
+ fn common(&self, ctx: &Context, workspace: &Workspace) -> &wgpu::BindGroup {
self.common.get_or_init(|| {
ctx.gpu
.device
@@ -696,22 +696,26 @@ impl BindGroups {
entries: &[
wgpu::BindGroupEntry {
binding: 0,
- resource: buffers.config_buf.as_entire_binding(),
+ resource: workspace.config_buf.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 1,
- resource: buffers.tile_tapes.bind_active(),
+ resource: workspace.tile_tapes.bind_active(),
},
wgpu::BindGroupEntry {
binding: 2,
- resource: buffers.vars_buf.bind_active(),
+ resource: workspace.vars_buf.bind_active(),
},
],
})
})
}
- fn root_tiles(&self, ctx: &Context, buffers: &Buffers) -> &wgpu::BindGroup {
+ fn root_tiles(
+ &self,
+ ctx: &Context,
+ workspace: &Workspace,
+ ) -> &wgpu::BindGroup {
self.root_tiles.get_or_init(|| {
ctx.gpu
.device
@@ -721,11 +725,11 @@ impl BindGroups {
entries: &[
wgpu::BindGroupEntry {
binding: 0,
- resource: buffers.tile64.tiles.bind_active(),
+ resource: workspace.tile64.tiles.bind_active(),
},
wgpu::BindGroupEntry {
binding: 1,
- resource: buffers.tile64.values.bind_active(),
+ resource: workspace.tile64.values.bind_active(),
},
],
})
@@ -735,7 +739,7 @@ impl BindGroups {
fn interval_tiles(
&self,
ctx: &Context,
- buffers: &Buffers,
+ workspace: &Workspace,
) -> &wgpu::BindGroup {
self.interval_tiles.get_or_init(|| {
ctx.gpu
@@ -746,15 +750,15 @@ impl BindGroups {
entries: &[
wgpu::BindGroupEntry {
binding: 0,
- resource: buffers.tile64.tiles.bind_active(),
+ resource: workspace.tile64.tiles.bind_active(),
},
wgpu::BindGroupEntry {
binding: 1,
- resource: buffers.tile8.tiles.bind_active(),
+ resource: workspace.tile8.tiles.bind_active(),
},
wgpu::BindGroupEntry {
binding: 2,
- resource: buffers.tile8.values.bind_active(),
+ resource: workspace.tile8.values.bind_active(),
},
],
})
@@ -764,7 +768,7 @@ impl BindGroups {
fn pixel_tiles(
&self,
ctx: &Context,
- buffers: &Buffers,
+ workspace: &Workspace,
) -> &wgpu::BindGroup {
self.pixel_tiles.get_or_init(|| {
ctx.gpu
@@ -775,18 +779,18 @@ impl BindGroups {
entries: &[
wgpu::BindGroupEntry {
binding: 0,
- resource: buffers.tile8.tiles.bind_active(),
+ resource: workspace.tile8.tiles.bind_active(),
},
wgpu::BindGroupEntry {
binding: 1,
- resource: buffers.pixels.bind_active(),
+ resource: workspace.pixels.bind_active(),
},
],
})
})
}
- fn merge(&self, ctx: &Context, buffers: &Buffers) -> &wgpu::BindGroup {
+ fn merge(&self, ctx: &Context, workspace: &Workspace) -> &wgpu::BindGroup {
self.merge.get_or_init(|| {
ctx.gpu
.device
@@ -796,15 +800,15 @@ impl BindGroups {
entries: &[
wgpu::BindGroupEntry {
binding: 0,
- resource: buffers.tile64.values.bind_active(),
+ resource: workspace.tile64.values.bind_active(),
},
wgpu::BindGroupEntry {
binding: 1,
- resource: buffers.tile8.values.bind_active(),
+ resource: workspace.tile8.values.bind_active(),
},
wgpu::BindGroupEntry {
binding: 2,
- resource: buffers.pixels.bind_active(),
+ resource: workspace.pixels.bind_active(),
},
],
})
@@ -829,7 +833,7 @@ struct TileBuffers {
/// Error type when resizing root tile buffers
#[derive(Debug, thiserror::Error)]
#[error("failed to resize `{buf}` root tile buffer")]
-pub struct TileBuffersError {
+pub struct TileBufferError {
/// Buffer which failed to resize
pub buf: TileBufferName,
/// Error returned by buffer resizing
@@ -860,14 +864,14 @@ impl TileBuffers {
fn new(
device: &wgpu::Device,
render_size: TileRenderSize,
- ) -> Result {
+ ) -> Result {
// Allocate enough words to write all of the output tiles
let tiles = FlexBuffer::new(
device,
format!("tiles_out{N}"),
Self::tiles_buf_size(render_size),
)
- .map_err(|err| TileBuffersError {
+ .map_err(|err| TileBufferError {
buf: TileBufferName::Tiles,
err,
})?;
@@ -875,7 +879,7 @@ impl TileBuffers {
let values_buf_size = Self::values_buf_size(render_size);
let values =
FlexBuffer::new(device, format!("tile{N}_values"), values_buf_size)
- .map_err(|err| TileBuffersError {
+ .map_err(|err| TileBufferError {
buf: TileBufferName::Values,
err,
})?;
@@ -906,18 +910,18 @@ impl TileBuffers {
&mut self,
device: &wgpu::Device,
render_size: TileRenderSize,
- ) -> Result<(), TileBuffersError> {
+ ) -> Result<(), TileBufferError> {
// Destructure to make sure we take all members into account
let TileBuffers { tiles, values } = self;
tiles
.grow_to_fit(device, Self::tiles_buf_size(render_size))
- .map_err(|err| TileBuffersError {
+ .map_err(|err| TileBufferError {
buf: TileBufferName::Tiles,
err,
})?;
values
.grow_to_fit(device, Self::values_buf_size(render_size))
- .map_err(|err| TileBuffersError {
+ .map_err(|err| TileBufferError {
buf: TileBufferName::Values,
err,
})?;
@@ -1001,13 +1005,13 @@ impl Context {
}
}
- /// Builds a new [`Buffers`] object for use in rendering
+ /// Builds a new [`Workspace`] object for use in rendering
///
/// The buffers are initialized with a dummy size and resized automatically
/// when passed into any of the runner functions (e.g. [`run`](Self::run) or
/// [`submit`](Self::submit)).
- pub fn buffers(&self) -> Buffers {
- Buffers::new(&self.gpu.device)
+ pub fn workspace(&self) -> Workspace {
+ Workspace::new(&self.gpu.device)
}
/// Renders the image, with a blocking wait to read pixel data from the GPU
@@ -1017,11 +1021,11 @@ impl Context {
pub fn run(
&self,
shape: &RenderShape,
- buffers: &mut Buffers,
+ workspace: &mut Workspace,
out: &mut ReadBuffer,
settings: RenderConfig,
) -> Result {
- self.run_with_vars(shape, &Default::default(), buffers, out, settings)
+ self.run_with_vars(shape, &Default::default(), workspace, out, settings)
}
/// Renders the image, with a blocking wait to read pixel data from the GPU
@@ -1032,12 +1036,12 @@ impl Context {
&self,
shape: &RenderShape,
vars: &ShapeVars,
- buffers: &mut Buffers,
+ workspace: &mut Workspace,
out: &mut ReadBuffer,
settings: RenderConfig,
) -> Result {
- self.submit_with_vars(shape, vars, buffers, &settings)?;
- self.gpu.copy(buffers.output(), out);
+ self.submit_with_vars(shape, vars, workspace, &settings)?;
+ self.gpu.copy(workspace.output(), out);
let image = self.gpu.map_image(out);
Ok(image.image())
}
@@ -1046,14 +1050,14 @@ impl Context {
pub async fn run_async(
&self,
shape: &RenderShape,
- buffers: &mut Buffers,
+ workspace: &mut Workspace,
out: &mut ReadBuffer,
settings: RenderConfig,
) -> Result {
self.run_with_vars_async(
shape,
&Default::default(),
- buffers,
+ workspace,
out,
settings,
)
@@ -1065,12 +1069,12 @@ impl Context {
&self,
shape: &RenderShape,
vars: &ShapeVars,
- buffers: &mut Buffers,
+ workspace: &mut Workspace,
out: &mut ReadBuffer,
settings: RenderConfig,
) -> Result {
- self.submit_with_vars(shape, vars, buffers, &settings)?;
- self.gpu.copy(buffers.output(), out);
+ self.submit_with_vars(shape, vars, workspace, &settings)?;
+ self.gpu.copy(workspace.output(), out);
let image = self.gpu.map_image_async(out).await;
Ok(image.image())
}
@@ -1078,14 +1082,14 @@ impl Context {
/// Submits a single image to be rendered on the GPU
///
/// The resulting image (as a buffer of [`RawDistancePixel`] data) is
- /// available on the GPU in [`buffers.output()`](Buffers::output).
+ /// available on the GPU in [`buffers.output()`](Workspace::output).
pub fn submit(
&self,
shape: &RenderShape,
- buffers: &mut Buffers,
+ workspace: &mut Workspace,
settings: &RenderConfig,
) -> Result<(), SubmitError> {
- self.submit_with_vars(shape, &Default::default(), buffers, settings)
+ self.submit_with_vars(shape, &Default::default(), workspace, settings)
}
/// Submits a single image to be rendered on the GPU, with extra variables
@@ -1095,16 +1099,16 @@ impl Context {
&self,
shape: &RenderShape,
vars: &ShapeVars,
- buffers: &mut Buffers,
+ workspace: &mut Workspace,
settings: &RenderConfig,
) -> Result<(), SubmitError> {
- buffers.set_image_size(&self.gpu.device, settings.image_size)?;
- let render_size = TileRenderSize::from(buffers.image_size);
+ workspace.set_image_size(&self.gpu.device, settings.image_size)?;
+ let render_size = TileRenderSize::from(workspace.image_size);
// The WebGPU config type has a mat3x3f, but that type pads each row to
// 16 bytes, so we'll just use a mat4x4 for simplicity
let mat =
- settings.world_to_model * buffers.image_size.screen_to_world();
+ settings.world_to_model * workspace.image_size.screen_to_world();
let mut mat4 = nalgebra::Matrix4x3::::identity();
mat4.fixed_view_mut::<3, 3>(0, 0).copy_from(&mat);
@@ -1116,8 +1120,8 @@ impl Context {
render_size: [render_size.width(), render_size.height()],
tape_data_capacity: TAPE_DATA_CAPACITY.try_into().unwrap(),
image_size: [
- buffers.image_size.width(),
- buffers.image_size.height(),
+ workspace.image_size.width(),
+ workspace.image_size.height(),
],
tape_data_offset: start_offset,
z: settings.z,
@@ -1132,7 +1136,7 @@ impl Context {
.gpu
.queue
.write_buffer_with(
- &buffers.config_buf,
+ &workspace.config_buf,
0,
((config_len + shape.bytecode.as_bytes().len()) as u64)
.try_into()
@@ -1150,10 +1154,10 @@ impl Context {
// Copy vars (if present), then reset relevant bind groups if the buffer
// size has changed.
if matches!(
- shape.copy_vars(&self.gpu, vars, &mut buffers.vars_buf)?,
+ shape.copy_vars(&self.gpu, vars, &mut workspace.vars_buf)?,
CopyVarsChanged::BufferChanged
) {
- buffers.bind_groups.common = Default::default();
+ workspace.bind_groups.common = Default::default();
}
// Create a command encoder and dispatch the compute work
@@ -1162,7 +1166,7 @@ impl Context {
);
// Initial buffer reset pass
- self.reset_ctx.run(&mut encoder, buffers);
+ self.reset_ctx.run(&mut encoder, workspace);
let mut compute_pass =
encoder.begin_compute_pass(&wgpu::ComputePassDescriptor {
@@ -1171,26 +1175,26 @@ impl Context {
});
// Build the common config buffer
- let common_bind_group = buffers.bind_groups.common(self, buffers);
+ let common_bind_group = workspace.bind_groups.common(self, workspace);
compute_pass.set_bind_group(0, common_bind_group, &[]);
// Populate root tiles (64x64x64, densely packed)
self.root_ctx.run(
self,
- buffers,
+ workspace,
shape.bytecode.reg_count(),
render_size,
&mut compute_pass,
);
self.tiles_ctx.run(
self,
- buffers,
+ workspace,
shape.bytecode.reg_count(),
&mut compute_pass,
);
self.pixels_ctx.run(
self,
- buffers,
+ workspace,
shape.bytecode.reg_count(),
&mut compute_pass,
);
@@ -1198,7 +1202,7 @@ impl Context {
// Merge filled tiles from large -> small
self.merge_ctx.run(
self,
- buffers,
+ workspace,
settings.image_size,
&mut compute_pass,
);
@@ -1272,11 +1276,11 @@ impl MergeContext {
fn run(
&self,
ctx: &Context,
- buffers: &Buffers,
+ workspace: &Workspace,
render_size: ImageSize,
compute_pass: &mut wgpu::ComputePass,
) {
- let bind_group = buffers.bind_groups.merge(ctx, buffers);
+ let bind_group = workspace.bind_groups.merge(ctx, workspace);
compute_pass.set_pipeline(&self.pipeline);
compute_pass.set_bind_group(1, bind_group, &[]);
compute_pass.dispatch_workgroups(
@@ -1291,16 +1295,16 @@ impl MergeContext {
struct ResetContext;
impl ResetContext {
- fn run(&self, encoder: &mut wgpu::CommandEncoder, buffers: &Buffers) {
+ fn run(&self, encoder: &mut wgpu::CommandEncoder, workspace: &Workspace) {
// Clear `count` and `wg_size` members of the tile output buffers
- encoder.clear_buffer(buffers.tile64.tiles.data(), 0, Some(16));
- encoder.clear_buffer(buffers.tile8.tiles.data(), 0, Some(16));
- buffers.tile64.values.clear(encoder);
- buffers.tile8.values.clear(encoder);
- buffers.pixels.clear(encoder);
+ encoder.clear_buffer(workspace.tile64.tiles.data(), 0, Some(16));
+ encoder.clear_buffer(workspace.tile8.tiles.data(), 0, Some(16));
+ workspace.tile64.values.clear(encoder);
+ workspace.tile8.values.clear(encoder);
+ workspace.pixels.clear(encoder);
// Clear the whole tile tape map (TODO is this needed?)
- buffers.tile_tapes.clear(encoder);
+ workspace.tile_tapes.clear(encoder);
}
}
@@ -1348,8 +1352,8 @@ mod test {
let pixel_ctx = Context::new(&gpu);
let effects_ctx = effects::Context::new(&gpu);
- let mut buf = pixel_ctx.buffers();
- let mut merge_buf = effects_ctx.merge_buffers();
+ let mut buf = pixel_ctx.workspace();
+ let mut merge_buf = effects_ctx.merge_workspace();
// Render and accumulate each shape
for (shape, _) in shapes {
diff --git a/fidget-wgpu/src/voxel/effects/mod.rs b/fidget-wgpu/src/voxel/effects/mod.rs
index 7a4498c7..de04e69f 100644
--- a/fidget-wgpu/src/voxel/effects/mod.rs
+++ b/fidget-wgpu/src/voxel/effects/mod.rs
@@ -204,13 +204,13 @@ tag!(pub MergeVoxelBufferTag, PackedVoxel, VoxelSize, STORAGE | COPY_SRC,
);
/// Handle to a set of buffers used when merging images
-pub struct MergeBuffers {
+pub struct MergeWorkspace {
config: wgpu::Buffer,
out: FlexBuffer,
image_count: usize,
}
-impl MergeBuffers {
+impl MergeWorkspace {
/// Returns a handle to the output buffer
pub fn output(&self) -> &FlexBuffer {
&self.out
@@ -231,13 +231,13 @@ tag!(
);
/// Handle to a set of buffers used when shading images
-pub struct ShadeBuffers {
+pub struct ShadeWorkspace {
config: wgpu::Buffer,
has_color: bool,
out: FlexBuffer,
}
-impl ShadeBuffers {
+impl ShadeWorkspace {
/// Returns a reference to the output buffer
pub fn output(&self) -> &FlexBuffer {
&self.out
@@ -473,11 +473,11 @@ impl Context {
}
}
- /// Builds a new set of [`MergeBuffers`]
+ /// Builds a new set of [`MergeWorkspace`]
///
/// These will be resized when first used (in
/// [`submit_merge`](Self::submit_merge))
- pub fn merge_buffers(&self) -> MergeBuffers {
+ pub fn merge_workspace(&self) -> MergeWorkspace {
let config = self.gpu.device.create_buffer(&wgpu::BufferDescriptor {
label: Some("config"),
size: std::mem::size_of::() as u64,
@@ -486,19 +486,19 @@ impl Context {
});
let out = FlexBuffer::new(&self.gpu.device, "merge output", 64.into())
.expect("64 is always a valid size");
- MergeBuffers {
+ MergeWorkspace {
config,
out,
image_count: 0,
}
}
- /// Builds a new set of [`ShadeBuffers`]
+ /// Builds a new set of [`ShadeWorkspace`]
///
/// These will be resized when first used (in
/// either [`submit_color`](Self::submit_color) or
/// [`submit_shade`](Self::submit_shade))
- pub fn shade_buffers(&self) -> ShadeBuffers {
+ pub fn shade_workspace(&self) -> ShadeWorkspace {
let config = self.gpu.device.create_buffer(&wgpu::BufferDescriptor {
label: Some("shade config"),
size: std::mem::size_of::() as u64,
@@ -507,18 +507,18 @@ impl Context {
});
let out = FlexBuffer::new(&self.gpu.device, "shade output", 64.into())
.expect("64 is always a valid size");
- ShadeBuffers {
+ ShadeWorkspace {
config,
has_color: false,
out,
}
}
- /// Builds a new set of [`SsaoBuffers`]
+ /// Builds a new set of [`SsaoWorkspace`]
///
/// These will be resized when first used (in
/// [`submit_ssao`](Self::submit_ssao))
- pub fn ssao_buffers(&self) -> SsaoBuffers {
+ pub fn ssao_workspace(&self) -> SsaoWorkspace {
let ssao_config =
self.gpu.device.create_buffer(&wgpu::BufferDescriptor {
label: Some("ssao config"),
@@ -545,7 +545,7 @@ impl Context {
image_size,
)
.expect("64 is always a valid size");
- SsaoBuffers {
+ SsaoWorkspace {
ssao_config,
blur_config,
raw_occlusion,
@@ -555,14 +555,14 @@ impl Context {
/// Accumulates an image into a merged image buffer
///
- /// [`MergeBuffers::reset`] should be called before the first call to
+ /// [`MergeWorkspace::reset`] should be called before the first call to
/// `submit_merge`. For the first merge after a reset, the output buffer is
/// resized to fit the images; subsequent merges must be of the same size.
pub fn submit_merge(
&self,
image: &FlexBuffer,
settings: MergeSettings,
- buf: &mut MergeBuffers,
+ buf: &mut MergeWorkspace,
) -> Result<(), MergeError> {
let size = image.size();
if buf.image_count == 0 {
@@ -649,9 +649,9 @@ impl Context {
/// The output buffer is resized to fit the incoming image
pub fn submit_shade(
&self,
- image: &MergeBuffers,
- ssao: Option<&SsaoBuffers>,
- buf: &mut ShadeBuffers,
+ image: &MergeWorkspace,
+ ssao: Option<&SsaoWorkspace>,
+ buf: &mut ShadeWorkspace,
) -> Result<(), ShadeError> {
let size = image.out.size();
if buf.has_color {
@@ -748,8 +748,8 @@ impl Context {
/// The output buffer is resized to fit the incoming image
pub fn submit_heightmap(
&self,
- image: &MergeBuffers,
- buf: &mut ShadeBuffers,
+ image: &MergeWorkspace,
+ buf: &mut ShadeWorkspace,
) -> Result<(), HeightmapError> {
let size = image.out.size();
if buf.has_color {
@@ -828,24 +828,24 @@ impl Context {
/// Submits a pass to compute an SSAO buffer
pub fn submit_ssao(
&self,
- image: &MergeBuffers,
- buf: &mut SsaoBuffers,
+ image: &MergeWorkspace,
+ buf: &mut SsaoWorkspace,
) -> Result<(), SsaoError> {
self.ssao_ctx.submit(image, buf, &self.gpu)
}
/// Submits a color evaluation pass
///
- /// Image size is set from the `MergeBuffers`; the transform matrix is
+ /// Image size is set from the `MergeWorkspace`; the transform matrix is
/// provided separately (but should be the same one used for image
/// evaluation).
pub fn submit_color(
&self,
- merge: &MergeBuffers,
+ merge: &MergeWorkspace,
world_to_model: &nalgebra::Matrix4,
shape: &ShapeColorBuffers,
bufs: &mut ColorWorkspace,
- out: &mut ShadeBuffers,
+ out: &mut ShadeWorkspace,
) -> Result<(), ColorError> {
self.submit_color_with_vars(
merge,
@@ -859,17 +859,17 @@ impl Context {
/// Submits a color evaluation pass with auxiliary variables
///
- /// Image size is set from the `MergeBuffers`; the transform matrix is
+ /// Image size is set from the `MergeWorkspace`; the transform matrix is
/// provided separately (but should be the same one used for image
/// evaluation).
pub fn submit_color_with_vars(
&self,
- merge: &MergeBuffers,
+ merge: &MergeWorkspace,
world_to_model: &nalgebra::Matrix4,
shape: &ShapeColorBuffers,
bufs: &mut ColorWorkspace,
vars: &ShapeVars,
- out: &mut ShadeBuffers,
+ out: &mut ShadeWorkspace,
) -> Result<(), ColorError> {
self.color_ctx.submit(
merge,
@@ -896,7 +896,7 @@ tag!(pub SsaoBlurredBufferTag, f32, ImageSize, STORAGE | COPY_SRC,
"Tag for a blurred SSAO occlusion buffer");
/// Handle to a set of buffers used when running an SSAO pass
-pub struct SsaoBuffers {
+pub struct SsaoWorkspace {
ssao_config: wgpu::Buffer, // TODO add a `ConfigBuffer` type?
raw_occlusion: FlexBuffer,
@@ -904,7 +904,7 @@ pub struct SsaoBuffers {
blurred_occlusion: FlexBuffer,
}
-impl SsaoBuffers {
+impl SsaoWorkspace {
/// Returns a shared handle to the raw SSAO occlusion buffer
pub fn raw_occlusion(&self) -> &FlexBuffer {
&self.raw_occlusion
@@ -1085,8 +1085,8 @@ impl SsaoContext {
fn submit(
&self,
- image: &MergeBuffers,
- buf: &mut SsaoBuffers,
+ image: &MergeWorkspace,
+ buf: &mut SsaoWorkspace,
gpu: &Gpu,
) -> Result<(), SsaoError> {
let image_size = image.out.size();
@@ -1279,12 +1279,12 @@ impl ColorContext {
#[allow(clippy::too_many_arguments)] // what are ya gonna do?
fn submit(
&self,
- image: &MergeBuffers,
+ image: &MergeWorkspace,
world_to_model: &nalgebra::Matrix4,
shape: &ShapeColorBuffers,
bufs: &mut ColorWorkspace,
vars: &ShapeVars,
- out: &mut ShadeBuffers,
+ out: &mut ShadeWorkspace,
gpu: &Gpu,
) -> Result<(), ColorError> {
if image.image_count != shape.shape_count() {
@@ -1429,8 +1429,8 @@ mod test {
let size = 128;
let image_size = RenderSize::from(size);
- let mut buf = voxel_ctx.buffers();
- let mut merge_buf = effects_ctx.merge_buffers();
+ let mut voxel_buf = voxel_ctx.workspace();
+ let mut merge_buf = effects_ctx.merge_workspace();
let (x, y, z) = Tree::axes();
let sphere =
@@ -1441,7 +1441,7 @@ mod test {
voxel_ctx
.submit(
&shape,
- &mut buf,
+ &mut voxel_buf,
&crate::voxel::RenderConfig {
image_size,
world_to_model: nalgebra::Matrix4::identity(),
@@ -1449,9 +1449,13 @@ mod test {
)
.unwrap();
effects_ctx
- .submit_merge(buf.output(), Default::default(), &mut merge_buf)
+ .submit_merge(
+ voxel_buf.output(),
+ Default::default(),
+ &mut merge_buf,
+ )
.unwrap();
- let mut ssao_buf = effects_ctx.ssao_buffers();
+ let mut ssao_buf = effects_ctx.ssao_workspace();
effects_ctx.submit_ssao(&merge_buf, &mut ssao_buf).unwrap();
let ssao_out = gpu.read_vec(ssao_buf.raw_occlusion());
diff --git a/fidget-wgpu/src/voxel/mod.rs b/fidget-wgpu/src/voxel/mod.rs
index 964d648f..6ea62110 100644
--- a/fidget-wgpu/src/voxel/mod.rs
+++ b/fidget-wgpu/src/voxel/mod.rs
@@ -53,14 +53,14 @@
//! - [`RenderShape`] contains serialized bytecode to render a particular shape.
//! Best practice is to rebuild it only when a shape changes (i.e. not once
//! per frame), although in practice it's pretty fast to construct.
-//! - [`Buffers`] contains GPU buffers needed for rendering at a particular
+//! - [`Workspace`] contains GPU buffers needed for rendering at a particular
//! image size. It is primarily expensive in GPU memory, as it contains
-//! several full-frame buffers. Best practice is to construct one [`Buffers`]
-//! object per worker context (or per simultaneous render); it will be
-//! automatically resized when used. Systems with high variability in image
-//! size may want to periodically compare [`size`](Buffers::size) versus
-//! [`capacity`](Buffers::capacity) and fully reallocate buffers (by
-//! constructing a new `Buffers` object) if they get too out of whack.
+//! several full-frame buffers. Best practice is to construct one
+//! [`Workspace`] object per worker context (or per simultaneous render); it
+//! will be automatically resized when used. Systems with high variability in
+//! image size may want to periodically compare [`size`](Workspace::size)
+//! versus [`capacity`](Workspace::capacity) and fully reallocate buffers (by
+//! constructing a new `Workspace` object) if they get too out of whack.
//! - [`RenderConfig`] sets the transform matrix for rendering. This is cheap
//! to construct and could be built once per frame
//!
@@ -68,7 +68,7 @@
//! - Build a [`Context`]
//! - Use [`RenderShape::new`] to convert from a
//! [`VmShape`](fidget_core::vm::VmShape) to a [`RenderShape`]
-//! - Use [`Context::buffers`] to get [`Buffers`] at a particular image size
+//! - Use [`Context::workspace`] to get [`Workspace`]
//! - Use [`Gpu::read_buffer_for(buffers.output())`](Gpu::read_buffer_for) to
//! get an output buffer
//! - Call [`Context::run`] or [`Context::run_async`] to get an image
@@ -93,8 +93,8 @@
//! - Read image data back to the CPU
//!
//! Lower-level building blocks are also available: [`Context::submit`] submits
-//! the render operations to the GPU, and [`Buffers::output`] returns the output
-//! buffer.
+//! the render operations to the GPU, and [`Workspace::output`] returns the
+//! output buffer.
use crate::{
CopyVarsChanged, CopyVarsError, Gpu, RegPipeline, RenderShape,
@@ -228,10 +228,10 @@ impl std::fmt::Display for BufferName {
}
}
-/// Error returned when resizing a [`Buffers`] object
+/// Error returned when resizing buffers in a [`Workspace`] object
#[derive(Debug, thiserror::Error)]
#[error("failed to build {buf} buffer")]
-pub struct BuffersError {
+pub struct BufferError {
/// Buffer which failed to resize
pub buf: BufferName,
/// Error returned by buffer resizing
@@ -247,14 +247,14 @@ pub enum SubmitError {
MissingVar(#[from] MissingVar),
/// Error while resizing buffers
#[error(transparent)]
- Buffers(#[from] BuffersError),
+ Buffer(#[from] BufferError),
}
impl From for SubmitError {
fn from(value: CopyVarsError) -> Self {
match value {
CopyVarsError::MissingVar(v) => Self::MissingVar(v),
- CopyVarsError::BufferSize(err) => Self::Buffers(BuffersError {
+ CopyVarsError::BufferSize(err) => Self::Buffer(BufferError {
buf: BufferName::Vars,
err,
}),
@@ -504,12 +504,12 @@ impl RootContext {
fn run(
&self,
ctx: &Context,
- buffers: &Buffers,
+ workspace: &Workspace,
reg_count: u8,
render_size: TileRenderSize,
compute_pass: &mut wgpu::ComputePass,
) {
- let bind_group = buffers.bind_groups.root(ctx, buffers);
+ let bind_group = workspace.bind_groups.root(ctx, workspace);
compute_pass.set_pipeline(self.root_pipeline.get(reg_count));
compute_pass.set_bind_group(1, bind_group, &[]);
@@ -582,11 +582,11 @@ impl RepackContext {
fn run(
&self,
ctx: &Context,
- buffers: &Buffers,
+ workspace: &Workspace,
render_size: TileRenderSize,
compute_pass: &mut wgpu::ComputePass,
) {
- let bind_group = buffers.bind_groups.repack(ctx, buffers);
+ let bind_group = workspace.bind_groups.repack(ctx, workspace);
compute_pass.set_pipeline(&self.repack_pipeline);
compute_pass.set_bind_group(1, bind_group, &[]);
@@ -792,14 +792,15 @@ impl IntervalContext {
fn run(
&self,
ctx: &Context,
- buffers: &Buffers,
+ workspace: &Workspace,
strata: u64,
reg_count: u8,
compute_pass: &mut wgpu::ComputePass,
) {
- let strata_bytes = u64::try_from(buffers.strata_size_bytes()).unwrap();
+ let strata_bytes =
+ u64::try_from(workspace.strata_size_bytes()).unwrap();
let offset_bytes = strata * strata_bytes;
- let bind_group16 = buffers.bind_groups.interval16(ctx, buffers);
+ let bind_group16 = workspace.bind_groups.interval16(ctx, workspace);
compute_pass.set_pipeline(self.interval64_pipeline.get(reg_count));
compute_pass.set_bind_group(
1,
@@ -807,27 +808,27 @@ impl IntervalContext {
&[u32::try_from(offset_bytes).unwrap()],
);
compute_pass.dispatch_workgroups_indirect(
- buffers.tile64.strata.data(),
+ workspace.tile64.strata.data(),
offset_bytes,
);
- let bind_group_sort16 = buffers.bind_groups.sort16(ctx, buffers);
+ let bind_group_sort16 = workspace.bind_groups.sort16(ctx, workspace);
compute_pass.set_pipeline(&self.sort16_pipeline);
compute_pass.set_bind_group(1, bind_group_sort16, &[]);
compute_pass
- .dispatch_workgroups_indirect(buffers.tile16.tiles.data(), 0);
+ .dispatch_workgroups_indirect(workspace.tile16.tiles.data(), 0);
- let bind_group4 = buffers.bind_groups.interval4(ctx, buffers);
+ let bind_group4 = workspace.bind_groups.interval4(ctx, workspace);
compute_pass.set_pipeline(self.interval16_pipeline.get(reg_count));
compute_pass.set_bind_group(1, bind_group4, &[0]);
compute_pass
- .dispatch_workgroups_indirect(buffers.tile16.sorted.data(), 0);
+ .dispatch_workgroups_indirect(workspace.tile16.sorted.data(), 0);
- let bind_group_sort4 = buffers.bind_groups.sort4(ctx, buffers);
+ let bind_group_sort4 = workspace.bind_groups.sort4(ctx, workspace);
compute_pass.set_pipeline(&self.sort4_pipeline);
compute_pass.set_bind_group(1, bind_group_sort4, &[]);
compute_pass
- .dispatch_workgroups_indirect(buffers.tile4.tiles.data(), 0);
+ .dispatch_workgroups_indirect(workspace.tile4.tiles.data(), 0);
}
}
@@ -903,18 +904,18 @@ impl VoxelContext {
fn run(
&self,
ctx: &Context,
- buffers: &Buffers,
+ workspace: &Workspace,
reg_count: u8,
compute_pass: &mut wgpu::ComputePass,
) {
- let bind_group = buffers.bind_groups.voxel(ctx, buffers);
+ let bind_group = workspace.bind_groups.voxel(ctx, workspace);
compute_pass.set_pipeline(self.voxel_pipeline.get(reg_count));
compute_pass.set_bind_group(1, bind_group, &[]);
// Each workgroup is 4x4x4, i.e. covering a 4x4 splat of pixels with 4x
// workers in the Z direction.
compute_pass
- .dispatch_workgroups_indirect(buffers.tile4.sorted.data(), 0);
+ .dispatch_workgroups_indirect(workspace.tile4.sorted.data(), 0);
}
}
@@ -976,17 +977,17 @@ impl NormalsContext {
fn run(
&self,
ctx: &Context,
- buffers: &Buffers,
+ workspace: &Workspace,
reg_count: u8,
compute_pass: &mut wgpu::ComputePass,
) {
- let bind_group = buffers.bind_groups.normals(ctx, buffers);
+ let bind_group = workspace.bind_groups.normals(ctx, workspace);
compute_pass.set_pipeline(self.normals_pipeline.get(reg_count));
compute_pass.set_bind_group(1, bind_group, &[]);
compute_pass.dispatch_workgroups(
- buffers.image_size.width().div_ceil(8),
- buffers.image_size.height().div_ceil(8),
+ workspace.image_size.width().div_ceil(8),
+ workspace.image_size.height().div_ceil(8),
1,
);
}
@@ -1299,11 +1300,11 @@ tag!(pub GeomBufferTag, GeometryPixel, VoxelSize, STORAGE | COPY_SRC | COPY_DST,
"Tag for a on-GPU buffer storing [`GeometryPixel`] values");
tag!(pub(crate) VarsBufferTag, f32, usize, STORAGE | COPY_DST);
-/// Buffers for rendering
+/// Workspace for rendering
///
-/// This object is constructed by [`Context::buffers`] and may only be used with
+/// This object is constructed by [`Context::workspace`] and may only be used with
/// that particular [`Context`].
-pub struct Buffers {
+pub struct Workspace {
/// Image render size
///
/// Note that the tile buffers below round up to the nearest root tile
@@ -1366,7 +1367,7 @@ struct BindGroups {
}
impl BindGroups {
- fn common(&self, ctx: &Context, buffers: &Buffers) -> &wgpu::BindGroup {
+ fn common(&self, ctx: &Context, workspace: &Workspace) -> &wgpu::BindGroup {
self.common.get_or_init(|| {
ctx.gpu
.device
@@ -1376,22 +1377,22 @@ impl BindGroups {
entries: &[
wgpu::BindGroupEntry {
binding: 0,
- resource: buffers.config_buf.as_entire_binding(),
+ resource: workspace.config_buf.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 1,
- resource: buffers.tile_tapes.bind_active(),
+ resource: workspace.tile_tapes.bind_active(),
},
wgpu::BindGroupEntry {
binding: 2,
- resource: buffers.vars_buf.bind_active(),
+ resource: workspace.vars_buf.bind_active(),
},
],
})
})
}
- fn clear(&self, ctx: &Context, buffers: &Buffers) -> &wgpu::BindGroup {
+ fn clear(&self, ctx: &Context, workspace: &Workspace) -> &wgpu::BindGroup {
self.clear.get_or_init(|| {
ctx.gpu
.device
@@ -1401,7 +1402,7 @@ impl BindGroups {
entries: &[
wgpu::BindGroupEntry {
binding: 0,
- resource: buffers
+ resource: workspace
.tile16
.tiles
.data()
@@ -1410,7 +1411,7 @@ impl BindGroups {
},
wgpu::BindGroupEntry {
binding: 1,
- resource: buffers
+ resource: workspace
.tile16
.sorted
.data()
@@ -1419,7 +1420,7 @@ impl BindGroups {
},
wgpu::BindGroupEntry {
binding: 2,
- resource: buffers
+ resource: workspace
.tile4
.tiles
.data()
@@ -1428,7 +1429,7 @@ impl BindGroups {
},
wgpu::BindGroupEntry {
binding: 3,
- resource: buffers
+ resource: workspace
.tile4
.sorted
.data()
@@ -1437,14 +1438,14 @@ impl BindGroups {
},
wgpu::BindGroupEntry {
binding: 4,
- resource: buffers.z_hist_buf.as_entire_binding(),
+ resource: workspace.z_hist_buf.as_entire_binding(),
},
],
})
})
}
- fn merge(&self, ctx: &Context, buffers: &Buffers) -> &wgpu::BindGroup {
+ fn merge(&self, ctx: &Context, workspace: &Workspace) -> &wgpu::BindGroup {
self.merge.get_or_init(|| {
ctx.gpu
.device
@@ -1454,26 +1455,26 @@ impl BindGroups {
entries: &[
wgpu::BindGroupEntry {
binding: 0,
- resource: buffers.tile64.zmin.bind_active(),
+ resource: workspace.tile64.zmin.bind_active(),
},
wgpu::BindGroupEntry {
binding: 1,
- resource: buffers.tile16.zmin.bind_active(),
+ resource: workspace.tile16.zmin.bind_active(),
},
wgpu::BindGroupEntry {
binding: 2,
- resource: buffers.tile4.zmin.bind_active(),
+ resource: workspace.tile4.zmin.bind_active(),
},
wgpu::BindGroupEntry {
binding: 3,
- resource: buffers.voxels.bind_active(),
+ resource: workspace.voxels.bind_active(),
},
],
})
})
}
- fn root(&self, ctx: &Context, buffers: &Buffers) -> &wgpu::BindGroup {
+ fn root(&self, ctx: &Context, workspace: &Workspace) -> &wgpu::BindGroup {
self.root.get_or_init(|| {
ctx.gpu
.device
@@ -1483,18 +1484,18 @@ impl BindGroups {
entries: &[
wgpu::BindGroupEntry {
binding: 0,
- resource: buffers.tile64.tiles.bind_active(),
+ resource: workspace.tile64.tiles.bind_active(),
},
wgpu::BindGroupEntry {
binding: 1,
- resource: buffers.tile64.zmax.bind_active(),
+ resource: workspace.tile64.zmax.bind_active(),
},
],
})
})
}
- fn repack(&self, ctx: &Context, buffers: &Buffers) -> &wgpu::BindGroup {
+ fn repack(&self, ctx: &Context, workspace: &Workspace) -> &wgpu::BindGroup {
self.repack.get_or_init(|| {
ctx.gpu
.device
@@ -1504,23 +1505,28 @@ impl BindGroups {
entries: &[
wgpu::BindGroupEntry {
binding: 0,
- resource: buffers.tile64.tiles.bind_active(),
+ resource: workspace.tile64.tiles.bind_active(),
},
wgpu::BindGroupEntry {
binding: 1,
- resource: buffers.tile64.zmax.bind_active(),
+ resource: workspace.tile64.zmax.bind_active(),
},
wgpu::BindGroupEntry {
binding: 2,
- resource: buffers.tile64.strata.bind_active(),
+ resource: workspace.tile64.strata.bind_active(),
},
],
})
})
}
- fn interval16(&self, ctx: &Context, buffers: &Buffers) -> &wgpu::BindGroup {
- let strata_bytes = u64::try_from(buffers.strata_size_bytes()).unwrap();
+ fn interval16(
+ &self,
+ ctx: &Context,
+ workspace: &Workspace,
+ ) -> &wgpu::BindGroup {
+ let strata_bytes =
+ u64::try_from(workspace.strata_size_bytes()).unwrap();
self.interval16.get_or_init(|| {
ctx.gpu
.device
@@ -1530,7 +1536,7 @@ impl BindGroups {
entries: &[
wgpu::BindGroupEntry {
binding: 0,
- resource: buffers
+ resource: workspace
.tile64
.strata
.data()
@@ -1539,41 +1545,41 @@ impl BindGroups {
},
wgpu::BindGroupEntry {
binding: 1,
- resource: buffers.tile64.zmin.bind_active(),
+ resource: workspace.tile64.zmin.bind_active(),
},
wgpu::BindGroupEntry {
binding: 2,
- resource: buffers.tile16.tiles.bind_active(),
+ resource: workspace.tile16.tiles.bind_active(),
},
wgpu::BindGroupEntry {
binding: 3,
- resource: buffers.tile16.zmin.bind_active(),
+ resource: workspace.tile16.zmin.bind_active(),
},
wgpu::BindGroupEntry {
binding: 4,
- resource: buffers.z_hist_buf.slice(0..16).into(),
+ resource: workspace.z_hist_buf.slice(0..16).into(),
},
],
})
})
}
- fn sort16(&self, ctx: &Context, buffers: &Buffers) -> &wgpu::BindGroup {
+ fn sort16(&self, ctx: &Context, workspace: &Workspace) -> &wgpu::BindGroup {
self.sort16.get_or_init(|| {
Self::sort_bind_group(
ctx,
- &buffers.tile16,
- buffers.z_hist_buf.slice(0..16).into(),
+ &workspace.tile16,
+ workspace.z_hist_buf.slice(0..16).into(),
)
})
}
- fn sort4(&self, ctx: &Context, buffers: &Buffers) -> &wgpu::BindGroup {
+ fn sort4(&self, ctx: &Context, workspace: &Workspace) -> &wgpu::BindGroup {
self.sort4.get_or_init(|| {
Self::sort_bind_group(
ctx,
- &buffers.tile4,
- buffers.z_hist_buf.slice(256..320).into(),
+ &workspace.tile4,
+ workspace.z_hist_buf.slice(256..320).into(),
)
})
}
@@ -1605,7 +1611,11 @@ impl BindGroups {
})
}
- fn interval4(&self, ctx: &Context, buffers: &Buffers) -> &wgpu::BindGroup {
+ fn interval4(
+ &self,
+ ctx: &Context,
+ workspace: &Workspace,
+ ) -> &wgpu::BindGroup {
self.interval4.get_or_init(|| {
ctx.gpu
.device
@@ -1615,30 +1625,33 @@ impl BindGroups {
entries: &[
wgpu::BindGroupEntry {
binding: 0,
- resource: buffers.tile16.sorted.bind_active(),
+ resource: workspace.tile16.sorted.bind_active(),
},
wgpu::BindGroupEntry {
binding: 1,
- resource: buffers.tile16.zmin.bind_active(),
+ resource: workspace.tile16.zmin.bind_active(),
},
wgpu::BindGroupEntry {
binding: 2,
- resource: buffers.tile4.tiles.bind_active(),
+ resource: workspace.tile4.tiles.bind_active(),
},
wgpu::BindGroupEntry {
binding: 3,
- resource: buffers.tile4.zmin.bind_active(),
+ resource: workspace.tile4.zmin.bind_active(),
},
wgpu::BindGroupEntry {
binding: 4,
- resource: buffers.z_hist_buf.slice(256..320).into(),
+ resource: workspace
+ .z_hist_buf
+ .slice(256..320)
+ .into(),
},
],
})
})
}
- fn voxel(&self, ctx: &Context, buffers: &Buffers) -> &wgpu::BindGroup {
+ fn voxel(&self, ctx: &Context, workspace: &Workspace) -> &wgpu::BindGroup {
self.voxel.get_or_init(|| {
ctx.gpu
.device
@@ -1648,22 +1661,26 @@ impl BindGroups {
entries: &[
wgpu::BindGroupEntry {
binding: 0,
- resource: buffers.tile4.sorted.bind_active(),
+ resource: workspace.tile4.sorted.bind_active(),
},
wgpu::BindGroupEntry {
binding: 1,
- resource: buffers.tile4.zmin.bind_active(),
+ resource: workspace.tile4.zmin.bind_active(),
},
wgpu::BindGroupEntry {
binding: 2,
- resource: buffers.voxels.bind_active(),
+ resource: workspace.voxels.bind_active(),
},
],
})
})
}
- fn normals(&self, ctx: &Context, buffers: &Buffers) -> &wgpu::BindGroup {
+ fn normals(
+ &self,
+ ctx: &Context,
+ workspace: &Workspace,
+ ) -> &wgpu::BindGroup {
self.normals.get_or_init(|| {
ctx.gpu
.device
@@ -1673,11 +1690,11 @@ impl BindGroups {
entries: &[
wgpu::BindGroupEntry {
binding: 0,
- resource: buffers.voxels.bind_active(),
+ resource: workspace.voxels.bind_active(),
},
wgpu::BindGroupEntry {
binding: 1,
- resource: buffers.geom.bind_active(),
+ resource: workspace.geom.bind_active(),
},
],
})
@@ -1685,7 +1702,7 @@ impl BindGroups {
}
}
-impl Buffers {
+impl Workspace {
/// Returns the current image size
pub fn image_size(&self) -> VoxelSize {
self.image_size
@@ -1695,7 +1712,7 @@ impl Buffers {
///
/// This is intended for subsequent shaders which want to use the
/// [`GeometryPixel`] image data without copying to the CPU. It requires a
- /// exclusive borrow of the `Buffers` object (and then extends that
+ /// exclusive borrow of the `Workspace` object (and then extends that
/// lifetime) so that other callers can't simultaneously touch the buffer.
pub fn output(&mut self) -> &FlexBuffer {
&self.geom
@@ -1832,9 +1849,9 @@ impl Buffers {
&mut self,
device: &wgpu::Device,
image_size: VoxelSize,
- ) -> Result<(), BuffersError> {
+ ) -> Result<(), BufferError> {
let render_size = TileRenderSize::from(image_size);
- let Buffers {
+ let Workspace {
image_size: image_size_ref,
config_buf: _,
z_hist_buf: _,
@@ -1856,37 +1873,37 @@ impl Buffers {
*image_size_ref = image_size;
tile_tapes
.grow_to_fit(device, Self::tile_tapes_buf_size(render_size))
- .map_err(|err| BuffersError {
+ .map_err(|err| BufferError {
buf: BufferName::TileTapes,
err,
})?;
tile64
.grow_to_fit(device, render_size)
- .map_err(|e| BuffersError {
+ .map_err(|e| BufferError {
buf: BufferName::Tile64(e.buf),
err: e.err,
})?;
tile16
.grow_to_fit(device, render_size)
- .map_err(|e| BuffersError {
+ .map_err(|e| BufferError {
buf: BufferName::Tile16(e.buf),
err: e.err,
})?;
tile4
.grow_to_fit(device, render_size)
- .map_err(|e| BuffersError {
+ .map_err(|e| BufferError {
buf: BufferName::Tile4(e.buf),
err: e.err,
})?;
voxels
.grow_to_fit(device, Self::voxels_buf_size(render_size))
- .map_err(|err| BuffersError {
+ .map_err(|err| BufferError {
buf: BufferName::Voxels,
err,
})?;
geom.grow_to_fit(device, image_size)
- .map_err(|err| BuffersError {
+ .map_err(|err| BufferError {
buf: BufferName::Geom,
err,
})?;
@@ -1896,7 +1913,7 @@ impl Buffers {
/// Returns total allocated size (in bytes)
pub fn capacity(&self) -> u64 {
// Destructure to make sure we take all members into account
- let Buffers {
+ let Workspace {
image_size: _,
config_buf,
z_hist_buf,
@@ -1923,7 +1940,7 @@ impl Buffers {
/// Returns total active size (in bytes)
pub fn size(&self) -> u64 {
// Destructure to make sure we take all members into account
- let Buffers {
+ let Workspace {
image_size: _,
config_buf,
vars_buf,
@@ -1992,13 +2009,13 @@ impl Context {
}
}
- /// Builds a new [`Buffers`] object for use in rendering
+ /// Builds a new [`Workspace`] object for use in rendering
///
/// The buffers are initialized with a dummy size and resized automatically
/// when passed into any of the runner functions (e.g. [`run`](Self::run) or
/// [`submit`](Self::submit)).
- pub fn buffers(&self) -> Buffers {
- Buffers::new(&self.gpu.device)
+ pub fn workspace(&self) -> Workspace {
+ Workspace::new(&self.gpu.device)
}
/// Renders the image, with a blocking wait to read pixel data from the GPU
@@ -2008,11 +2025,11 @@ impl Context {
pub fn run(
&self,
shape: &RenderShape,
- buffers: &mut Buffers,
+ workspace: &mut Workspace,
out: &mut ReadBuffer,
settings: RenderConfig,
) -> Result {
- self.run_with_vars(shape, &Default::default(), buffers, out, settings)
+ self.run_with_vars(shape, &Default::default(), workspace, out, settings)
}
/// Renders the image, with a blocking wait to read pixel data from the GPU
@@ -2023,12 +2040,12 @@ impl Context {
&self,
shape: &RenderShape,
vars: &ShapeVars,
- buffers: &mut Buffers,
+ workspace: &mut Workspace,
out: &mut ReadBuffer,
settings: RenderConfig,
) -> Result {
- self.submit_with_vars(shape, vars, buffers, &settings)?;
- self.gpu.copy(&buffers.geom, out);
+ self.submit_with_vars(shape, vars, workspace, &settings)?;
+ self.gpu.copy(&workspace.geom, out);
let image = self.gpu.map_image(out);
Ok(image.image())
}
@@ -2039,14 +2056,14 @@ impl Context {
pub async fn run_async(
&self,
shape: &RenderShape,
- buffers: &mut Buffers,
+ workspace: &mut Workspace,
out: &mut ReadBuffer,
settings: RenderConfig,
) -> Result {
self.run_with_vars_async(
shape,
&Default::default(),
- buffers,
+ workspace,
out,
settings,
)
@@ -2060,12 +2077,12 @@ impl Context {
&self,
shape: &RenderShape,
vars: &ShapeVars,
- buffers: &mut Buffers,
+ workspace: &mut Workspace,
out: &mut ReadBuffer,
settings: RenderConfig,
) -> Result {
- self.submit_with_vars(shape, vars, buffers, &settings)?;
- self.gpu.copy(&buffers.geom, out);
+ self.submit_with_vars(shape, vars, workspace, &settings)?;
+ self.gpu.copy(&workspace.geom, out);
let image = self.gpu.map_image_async(out).await;
Ok(image.image())
}
@@ -2073,14 +2090,14 @@ impl Context {
/// Submits a single image to be rendered on the GPU
///
/// The resulting image (as a buffer of [`GeometryPixel`] data) is available
- /// on the GPU in [`buffers.output()`](Buffers::output).
+ /// on the GPU in [`workspace.output()`](Workspace::output).
pub fn submit(
&self,
shape: &RenderShape,
- buffers: &mut Buffers,
+ workspace: &mut Workspace,
settings: &RenderConfig,
) -> Result<(), SubmitError> {
- self.submit_with_vars(shape, &Default::default(), buffers, settings)
+ self.submit_with_vars(shape, &Default::default(), workspace, settings)
}
/// Submits a single image to be rendered on the GPU, with extra variables
@@ -2090,14 +2107,34 @@ impl Context {
&self,
shape: &RenderShape,
vars: &ShapeVars,
- buffers: &mut Buffers,
+ workspace: &mut Workspace,
+ settings: &RenderConfig,
+ ) -> Result<(), SubmitError> {
+ // Create a command encoder and dispatch the compute work
+ let mut encoder = self.gpu.device.create_command_encoder(
+ &wgpu::CommandEncoderDescriptor { label: None },
+ );
+ self.encode_with_vars(shape, vars, workspace, settings, &mut encoder)?;
+ self.gpu.queue.submit(Some(encoder.finish()));
+ Ok(())
+ }
+
+ /// Encodes a single image to be rendered on the GPU, with extra variables
+ ///
+ /// See [`submit`](Self::submit) for additional details.
+ pub fn encode_with_vars(
+ &self,
+ shape: &RenderShape,
+ vars: &ShapeVars,
+ workspace: &mut Workspace,
settings: &RenderConfig,
+ encoder: &mut wgpu::CommandEncoder,
) -> Result<(), SubmitError> {
- buffers.set_image_size(&self.gpu.device, settings.image_size)?;
- let render_size = TileRenderSize::from(buffers.image_size);
+ workspace.set_image_size(&self.gpu.device, settings.image_size)?;
+ let render_size = TileRenderSize::from(workspace.image_size);
let mat =
- settings.world_to_model * buffers.image_size.screen_to_world();
+ settings.world_to_model * workspace.image_size.screen_to_world();
// Divide by 2 to go from `u32` -> `TapeWord`
let start_offset = u32::try_from(shape.bytecode.len()).unwrap() / 2;
@@ -2111,9 +2148,9 @@ impl Context {
],
tape_data_capacity: TAPE_DATA_CAPACITY.try_into().unwrap(),
image_size: [
- buffers.image_size.width(),
- buffers.image_size.height(),
- buffers.image_size.depth(),
+ workspace.image_size.width(),
+ workspace.image_size.height(),
+ workspace.image_size.depth(),
],
tape_data_offset: start_offset,
root_tape_len: start_offset,
@@ -2126,7 +2163,7 @@ impl Context {
.gpu
.queue
.write_buffer_with(
- &buffers.config_buf,
+ &workspace.config_buf,
0,
((config_len + shape.bytecode.as_bytes().len()) as u64)
.try_into()
@@ -2144,19 +2181,14 @@ impl Context {
// Copy vars (if present), then reset relevant bind groups if the buffer
// size has changed.
if matches!(
- shape.copy_vars(&self.gpu, vars, &mut buffers.vars_buf)?,
+ shape.copy_vars(&self.gpu, vars, &mut workspace.vars_buf)?,
CopyVarsChanged::BufferChanged
) {
- buffers.bind_groups.common = Default::default();
+ workspace.bind_groups.common = Default::default();
}
- // Create a command encoder and dispatch the compute work
- let mut encoder = self.gpu.device.create_command_encoder(
- &wgpu::CommandEncoderDescriptor { label: None },
- );
-
// Initial buffer reset pass
- self.reset_ctx.run(&mut encoder, buffers);
+ self.reset_ctx.run(encoder, workspace);
let mut compute_pass =
encoder.begin_compute_pass(&wgpu::ComputePassDescriptor {
@@ -2165,53 +2197,51 @@ impl Context {
});
// Build the common config buffer
- let common_bind_group = buffers.bind_groups.common(self, buffers);
+ let common_bind_group = workspace.bind_groups.common(self, workspace);
compute_pass.set_bind_group(0, common_bind_group, &[]);
// Populate root tiles (64x64x64, densely packed)
self.root_ctx.run(
self,
- buffers,
+ workspace,
shape.bytecode.reg_count(),
render_size,
&mut compute_pass,
);
// Repack root tiles into strata
self.repack_ctx
- .run(self, buffers, render_size, &mut compute_pass);
+ .run(self, workspace, render_size, &mut compute_pass);
// Evaluate tiles in reverse-Z order by strata (64 voxels deep)
let strata_count = u64::from(render_size.depth()).div_ceil(64);
for strata in 0..strata_count {
self.interval_ctx.run(
self,
- buffers,
+ workspace,
strata,
shape.bytecode.reg_count(),
&mut compute_pass,
);
self.voxel_ctx.run(
self,
- buffers,
+ workspace,
shape.bytecode.reg_count(),
&mut compute_pass,
);
// Merge filled tiles from large -> small, populating the heightmap
- self.merge_ctx.run(self, buffers, &mut compute_pass);
+ self.merge_ctx.run(self, workspace, &mut compute_pass);
self.normals_ctx.run(
self,
- buffers,
+ workspace,
shape.bytecode.reg_count(),
&mut compute_pass,
);
- self.clear_ctx.run(self, buffers, &mut compute_pass);
+ self.clear_ctx.run(self, workspace, &mut compute_pass);
}
- drop(compute_pass);
// Submit the commands and wait for the GPU to complete
- self.gpu.queue.submit(Some(encoder.finish()));
Ok(())
}
}
@@ -2277,10 +2307,10 @@ impl ClearContext {
fn run(
&self,
ctx: &Context,
- buffers: &Buffers,
+ workspace: &Workspace,
compute_pass: &mut wgpu::ComputePass,
) {
- let bind_group = buffers.bind_groups.clear(ctx, buffers);
+ let bind_group = workspace.bind_groups.clear(ctx, workspace);
compute_pass.set_pipeline(&self.pipeline);
compute_pass.set_bind_group(1, bind_group, &[]);
compute_pass.dispatch_workgroups(1, 1, 1);
@@ -2348,11 +2378,11 @@ impl MergeContext {
fn run(
&self,
ctx: &Context,
- buffers: &Buffers,
+ workspace: &Workspace,
compute_pass: &mut wgpu::ComputePass,
) {
- let render_size = buffers.render_size();
- let bind_group = buffers.bind_groups.merge(ctx, buffers);
+ let render_size = workspace.render_size();
+ let bind_group = workspace.bind_groups.merge(ctx, workspace);
compute_pass.set_pipeline(&self.pipeline);
compute_pass.set_bind_group(1, bind_group, &[]);
compute_pass.dispatch_workgroups(
@@ -2366,32 +2396,32 @@ impl MergeContext {
struct ResetContext;
impl ResetContext {
- fn run(&self, encoder: &mut wgpu::CommandEncoder, buffers: &Buffers) {
+ fn run(&self, encoder: &mut wgpu::CommandEncoder, workspace: &Workspace) {
// Clear only the `count` member of the tile64 `tiles_out` buffer
- encoder.clear_buffer(buffers.tile64.tiles.data(), 12, Some(4));
+ encoder.clear_buffer(workspace.tile64.tiles.data(), 12, Some(4));
// Per-strata counters may now be at a different location in memory if
// we're using the buffers for multiple renders of different sizes! To
// be safe, we'll clear them here, rather than in a render pass.
- let strata_size_bytes = buffers.strata_size_bytes();
- for s in 0..buffers.render_size().nz() {
+ let strata_size_bytes = workspace.strata_size_bytes();
+ for s in 0..workspace.render_size().nz() {
encoder.clear_buffer(
- buffers.tile64.strata.data(),
+ workspace.tile64.strata.data(),
u64::from(s) * u64::try_from(strata_size_bytes).unwrap(),
Some(16),
);
}
// Clear all of the heightmaps and output maps
- buffers.tile64.zmin.clear(encoder);
- buffers.tile64.zmax.clear(encoder);
- buffers.tile16.zmin.clear(encoder);
- buffers.tile4.zmin.clear(encoder);
- buffers.voxels.clear(encoder);
- buffers.geom.clear(encoder);
+ workspace.tile64.zmin.clear(encoder);
+ workspace.tile64.zmax.clear(encoder);
+ workspace.tile16.zmin.clear(encoder);
+ workspace.tile4.zmin.clear(encoder);
+ workspace.voxels.clear(encoder);
+ workspace.geom.clear(encoder);
// Clear the whole tile tape map (TODO is this needed?)
- buffers.tile_tapes.clear(encoder);
+ workspace.tile_tapes.clear(encoder);
// tiles / sorted counters and z_hist are reset in clear shader
}
@@ -2479,9 +2509,9 @@ mod test {
let voxel_ctx = Context::new(&gpu);
let effects_ctx = effects::Context::new(&gpu);
- let mut buf = voxel_ctx.buffers();
- let mut merge_buf = effects_ctx.merge_buffers();
- let mut shade_buf = effects_ctx.shade_buffers();
+ let mut buf = voxel_ctx.workspace();
+ let mut merge_buf = effects_ctx.merge_workspace();
+ let mut shade_buf = effects_ctx.shade_workspace();
// Render and accumulate each shape
for (shape, _) in shapes {
@@ -2512,7 +2542,7 @@ mod test {
let mut color_workspace = effects_ctx.color_workspace();
// Compute SSAO buffer
- let mut ssao_buf = effects_ctx.ssao_buffers();
+ let mut ssao_buf = effects_ctx.ssao_workspace();
effects_ctx.submit_ssao(&merge_buf, &mut ssao_buf).unwrap();
// Compute per-pixel colors
diff --git a/fidget/tests/voxel_render.rs b/fidget/tests/voxel_render.rs
index f825b0a6..41e2aa41 100644
--- a/fidget/tests/voxel_render.rs
+++ b/fidget/tests/voxel_render.rs
@@ -111,7 +111,7 @@ mod wgpu {
let size = 32;
let image_size = RenderSize::from(size);
- let mut buf = ctx.buffers();
+ let mut buf = ctx.workspace();
let mut out = gpu.read_buffer_for(buf.output());
for scale in [1.0, 0.5] {
for r in [0.5, 0.75] {
@@ -163,7 +163,7 @@ mod wgpu {
let size = 32;
let image_size = RenderSize::from(size);
- let mut buf = ctx.buffers();
+ let mut buf = ctx.workspace();
let mut out = gpu.read_buffer_for(buf.output());
for scale in [1.0, 0.5] {
for r in [0.5, 0.75] {