use super::params::ParamValue;
use super::preview::fit_preview_dims;
use super::void::{Void, VoidRegistry};
struct PreviewTexture {
width: u32,
height: u32,
texture: wgpu::Texture,
view: wgpu::TextureView,
}
pub struct VoidPreviewRenderer {
target: Option<PreviewTexture>,
sampler: Option<wgpu::Sampler>,
}
impl VoidPreviewRenderer {
pub fn new() -> Self {
Self {
target: None,
sampler: None,
}
}
#[allow(clippy::too_many_arguments)]
pub fn build_void(
&mut self,
device: &wgpu::Device,
queue: &wgpu::Queue,
registry: &mut VoidRegistry,
type_id: &str,
params: &[ParamValue],
canvas_w: u32,
canvas_h: u32,
format: wgpu::TextureFormat,
) -> (Box<dyn Void>, super::effect::EffectCache) {
self.ensure_sampler(device);
let (pw, ph) = fit_preview_dims(canvas_w, canvas_h);
let realloc = match &self.target {
Some(t) => t.width != pw || t.height != ph,
None => true,
};
if realloc {
self.target = Some(make_texture(device, pw, ph, format));
}
let target = self.target.as_ref().unwrap();
let void = registry.create_void(type_id, params, device, format);
let cache = void.create_cache(
device,
queue,
&target.view,
self.sampler.as_ref().unwrap(),
target.width,
target.height,
);
(void, cache)
}
pub fn preview_size(&self) -> (u32, u32) {
self.target
.as_ref()
.map(|t| (t.width, t.height))
.unwrap_or((0, 0))
}
pub fn encode_frame(
&self,
encoder: &mut wgpu::CommandEncoder,
void: &dyn Void,
cache: &super::effect::EffectCache,
) {
let target = self.target.as_ref().unwrap();
void.encode(encoder, cache, &target.view);
}
pub fn output_texture(&self) -> &wgpu::Texture {
&self.target.as_ref().unwrap().texture
}
fn ensure_sampler(&mut self, device: &wgpu::Device) {
if self.sampler.is_none() {
self.sampler = Some(device.create_sampler(&wgpu::SamplerDescriptor {
label: Some("void-preview-sampler"),
mag_filter: wgpu::FilterMode::Linear,
min_filter: wgpu::FilterMode::Linear,
..Default::default()
}));
}
}
}
impl Default for VoidPreviewRenderer {
fn default() -> Self {
Self::new()
}
}
fn make_texture(
device: &wgpu::Device,
width: u32,
height: u32,
format: wgpu::TextureFormat,
) -> PreviewTexture {
let texture = device.create_texture(&wgpu::TextureDescriptor {
label: Some("void-preview-output"),
size: wgpu::Extent3d {
width,
height,
depth_or_array_layers: 1,
},
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format,
usage: wgpu::TextureUsages::RENDER_ATTACHMENT
| wgpu::TextureUsages::TEXTURE_BINDING
| wgpu::TextureUsages::COPY_SRC
| wgpu::TextureUsages::COPY_DST,
view_formats: &[],
});
let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
PreviewTexture {
width,
height,
texture,
view,
}
}