use super::GpuRenderer;
use crate::core::Rgba;
use crate::gpu::blur::BlurState;
use crate::gpu::scene::{PrimitiveKind, Scene};
pub(super) fn clear_color(clear: Rgba) -> wgpu::Color {
wgpu::Color { r: clear.r as f64, g: clear.g as f64, b: clear.b as f64, a: clear.a as f64 }
}
impl GpuRenderer {
pub(super) fn prepare_blur(&mut self, scene: &Scene, scale: f32) {
if !scene.has_blur() {
if let Some(blur) = &mut self.blur {
blur.idle_frame();
}
return;
}
let (device, queue) = (&self.context.device, &self.context.queue);
let format = self.context.config.format;
let size = (self.context.config.width, self.context.config.height);
let blur = self.blur.get_or_insert_with(|| BlurState::new(device, &self.pipelines, format));
blur.prepare(device, queue, &self.pipelines, scene, size, scale);
}
pub(super) fn encode_blurred(
&self,
encoder: &mut wgpu::CommandEncoder,
blur: &BlurState,
view: &wgpu::TextureView,
scene: &Scene,
clear: Rgba,
) {
let target = blur.scene_view();
let mut load = wgpu::LoadOp::Clear(clear_color(clear));
let mut segment = 0;
let draw = |encoder: &mut wgpu::CommandEncoder,
load: wgpu::LoadOp<wgpu::Color>,
batches: &[crate::gpu::scene::Batch]| {
let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("aura_pass"),
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
view: target,
depth_slice: None,
resolve_target: None,
ops: wgpu::Operations { load, store: wgpu::StoreOp::Store },
})],
..Default::default()
});
self.draw_batches(&mut pass, batches);
};
for (index, batch) in scene.batches.iter().enumerate() {
if batch.kind != PrimitiveKind::Blur {
continue;
}
if segment < index {
draw(encoder, load, &scene.batches[segment..index]);
load = wgpu::LoadOp::Load;
}
for instance in batch.range.clone() {
blur.blur_passes(encoder, instance as usize);
let one =
crate::gpu::scene::Batch { kind: PrimitiveKind::Blur, range: instance..instance + 1, transform: 0 };
draw(encoder, load, std::slice::from_ref(&one));
load = wgpu::LoadOp::Load;
}
segment = index + 1;
}
if segment < scene.batches.len() || segment == 0 {
draw(encoder, load, &scene.batches[segment..]);
}
blur.blit(encoder, view);
}
}