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
29 changes: 16 additions & 13 deletions fidget-wgpu/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ use fidget_core::{
use fidget_raster::RenderSize;

use heck::ToShoutySnakeCase;
use std::collections::BTreeMap;
use zerocopy::{FromBytes, Immutable, IntoBytes};

pub mod buf;
Expand Down Expand Up @@ -358,29 +357,33 @@ impl Gpu {
////////////////////////////////////////////////////////////////////////////////

/// Container of multiple pipelines, parameterized by register count
pub(crate) struct RegPipeline(BTreeMap<u8, wgpu::ComputePipeline>);
pub(crate) struct RegPipeline {
thunk: Box<dyn Fn(u8) -> wgpu::ComputePipeline>,
cache:
[std::cell::OnceCell<wgpu::ComputePipeline>; REG_PIPELINE_SIZES.len()],
}

const REG_PIPELINE_SIZES: &[u8] = &[8, 16, 32, 64, 128, 192, 255];

impl RegPipeline {
pub fn build<F: Fn(u8) -> wgpu::ComputePipeline>(builder: F) -> Self {
let mut out = BTreeMap::new();
for reg_count in [8, 16, 32, 64, 128, 192, 255] {
out.insert(reg_count, builder(reg_count));
pub fn build(builder: Box<dyn Fn(u8) -> wgpu::ComputePipeline>) -> Self {
Self {
thunk: builder,
cache: std::array::from_fn(|_| Default::default()),
}
Self(out)
}

/// Returns the pipeline with sufficient registers to render `reg_count`
///
/// # Panics
/// If `reg_count` is 256 (which is not allowed in bytecode tapes)
pub fn get(&self, reg_count: u8) -> &wgpu::ComputePipeline {
let (r, v) = self
.0
.range(reg_count..)
.next()
let (i, r) = REG_PIPELINE_SIZES
.iter()
.enumerate()
.find(|(_i, r)| reg_count <= **r)
.expect("bytecode tape cannot use more than 255 registers");
assert!(*r >= reg_count);
v
self.cache[i].get_or_init(|| (*self.thunk)(*r))
}
}

Expand Down
9 changes: 5 additions & 4 deletions fidget-wgpu/src/pixel/effects/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -475,22 +475,23 @@ impl ColorContext {
],
immediate_size: 0u32,
});
let color_pipeline = RegPipeline::build(|reg_count| {
let device_ = device.clone();
let color_pipeline = RegPipeline::build(Box::new(move |reg_count| {
let shader_code = color_shader(reg_count);
let shader_module =
device.create_shader_module(wgpu::ShaderModuleDescriptor {
device_.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(shader_code.into()),
});
device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
device_.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
label: Some(&format!("color ({reg_count})")),
layout: Some(&pipeline_layout),
module: &shader_module,
entry_point: Some("color_main"),
compilation_options: Default::default(),
cache: None,
})
});
}));

Self {
config_bind_group_layout,
Expand Down
27 changes: 15 additions & 12 deletions fidget-wgpu/src/pixel/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,22 +162,23 @@ impl RootContext {
immediate_size: 0u32,
});

let root_pipeline = RegPipeline::build(|reg_count| {
let device_ = device.clone();
let root_pipeline = RegPipeline::build(Box::new(move |reg_count| {
let shader_code = interval_root_shader(reg_count);
let shader_module =
device.create_shader_module(wgpu::ShaderModuleDescriptor {
device_.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(shader_code.into()),
});
device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
device_.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
label: Some(&format!("interval root ({reg_count})")),
layout: Some(&pipeline_layout),
module: &shader_module,
entry_point: Some("interval_root_main"),
compilation_options: Default::default(),
cache: None,
})
});
}));

Self {
bind_group_layout,
Expand Down Expand Up @@ -239,22 +240,23 @@ impl IntervalTilesContext {
immediate_size: 0u32,
});

let tiles_pipeline = RegPipeline::build(|reg_count| {
let device_ = device.clone();
let tiles_pipeline = RegPipeline::build(Box::new(move |reg_count| {
let shader_code = interval_tiles_shader(reg_count);
let shader_module =
device.create_shader_module(wgpu::ShaderModuleDescriptor {
device_.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(shader_code.into()),
});
device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
device_.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
label: Some(&format!("interval tiles ({reg_count})")),
layout: Some(&pipeline_layout),
module: &shader_module,
entry_point: Some("interval_tiles_main"),
compilation_options: Default::default(),
cache: None,
})
});
}));

Self {
bind_group_layout,
Expand Down Expand Up @@ -314,22 +316,23 @@ impl PixelTilesContext {
immediate_size: 0u32,
});

let tiles_pipeline = RegPipeline::build(|reg_count| {
let device_ = device.clone();
let tiles_pipeline = RegPipeline::build(Box::new(move |reg_count| {
let shader_code = pixel_tiles_shader(reg_count);
let shader_module =
device.create_shader_module(wgpu::ShaderModuleDescriptor {
device_.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(shader_code.into()),
});
device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
device_.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
label: Some(&format!("pixel tiles ({reg_count})")),
layout: Some(&pipeline_layout),
module: &shader_module,
entry_point: Some("pixel_tiles_main"),
compilation_options: Default::default(),
cache: None,
})
});
}));

Self {
bind_group_layout,
Expand Down
9 changes: 5 additions & 4 deletions fidget-wgpu/src/voxel/effects/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1251,22 +1251,23 @@ impl ColorContext {
],
immediate_size: 0u32,
});
let color_pipeline = RegPipeline::build(|reg_count| {
let device_ = device.clone();
let color_pipeline = RegPipeline::build(Box::new(move |reg_count| {
let shader_code = color_shader(reg_count);
let shader_module =
device.create_shader_module(wgpu::ShaderModuleDescriptor {
device_.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(shader_code.into()),
});
device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
device_.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
label: Some(&format!("color ({reg_count})")),
layout: Some(&pipeline_layout),
module: &shader_module,
entry_point: Some("color_main"),
compilation_options: Default::default(),
cache: None,
})
});
}));

Self {
config_bind_group_layout,
Expand Down
Loading