use crate::pyramid::ImagePyramid;
use crate::renderer::GpuRenderer;
impl GpuRenderer {
pub(crate) fn execute_pass_pyramid_build(
&mut self,
post_encoder: &mut wgpu::CommandEncoder,
scene_color_view: &wgpu::TextureView,
pyramid: &ImagePyramid,
) {
let kawase_uniform = self.device.create_buffer(&wgpu::BufferDescriptor {
label: Some("Kawase Pyramid Uniform"),
size: 32,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});
let mut views = Vec::new();
for mip in 0..pyramid.levels as usize {
match self.registry.get_texture_view(pyramid.mips[mip]) {
Some(v) => views.push(v),
None => {
tracing::error!("[Pyramid] Missing mip {} view, skipping", mip);
continue;
}
};
}
let mut current_w = pyramid.width as f32;
let mut current_h = pyramid.height as f32;
for mip in 0..pyramid.levels as usize {
let kernel_width = (mip as f32) + 1.0;
let uniform_data: [f32; 8] = [
current_w,
current_h,
mip as f32,
kernel_width,
0.0,
0.0,
0.0,
0.0,
];
self.queue
.write_buffer(&kawase_uniform, 0, bytemuck::cast_slice(&uniform_data));
let next_w = (current_w / 2.0).max(1.0);
let next_h = (current_h / 2.0).max(1.0);
let source_view = if mip == 0 {
scene_color_view
} else {
&views[mip - 1]
};
let target_view = &views[mip];
let bg = self.device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some(&format!("kawase_pyramid_bg_{}", mip)),
layout: &self.kawase_bind_group_layout,
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
buffer: &kawase_uniform,
offset: 0,
size: wgpu::BufferSize::new(32),
}),
},
wgpu::BindGroupEntry {
binding: 1,
resource: wgpu::BindingResource::TextureView(source_view),
},
wgpu::BindGroupEntry {
binding: 2,
resource: wgpu::BindingResource::Sampler(&self.sampler),
},
],
});
let mut p = post_encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some(&format!("Kawase Pyramid Down {}", mip)),
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
view: target_view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
r: 0.0,
g: 0.0,
b: 0.0,
a: 0.0,
}),
store: wgpu::StoreOp::Store,
},
depth_slice: None,
})],
..Default::default()
});
p.set_viewport(0.0, 0.0, next_w, next_h, 0.0, 1.0);
p.set_pipeline(&self.kawase_down_pipeline);
p.set_bind_group(0, &bg, &[]);
p.draw(0..3, 0..1);
current_w = next_w;
current_h = next_h;
}
tracing::trace!("[Kvasir] ImagePyramid build: {} levels", pyramid.levels);
}
}