use awsm_renderer_core::command::compute_pass::ComputePassDescriptor;
use crate::{
error::Result,
render::RenderContext,
render_passes::{
effects::{
bind_group::EffectsBindGroups,
pipeline::{EffectsPipelines, BLOOM_BLUR_PASSES},
shader::cache_key::BloomPhase,
},
RenderPassInitContext,
},
};
pub struct EffectsRenderPass {
pub bind_groups: EffectsBindGroups,
pub pipelines: EffectsPipelines,
}
impl EffectsRenderPass {
pub async fn new(ctx: &mut RenderPassInitContext<'_>) -> Result<Self> {
let bind_groups = EffectsBindGroups::new(ctx).await?;
let pipelines = EffectsPipelines::new(ctx, &bind_groups).await?;
Ok(Self {
bind_groups,
pipelines,
})
}
pub fn render(&self, ctx: &RenderContext) -> Result<()> {
let workgroup_size = (
ctx.render_texture_views.width.div_ceil(8),
ctx.render_texture_views.height.div_ceil(8),
);
if ctx.post_processing.bloom {
self.dispatch_pass(ctx, BloomPhase::Extract, false, workgroup_size)?;
for i in 0..BLOOM_BLUR_PASSES {
let ping_pong = (i + 1) % 2 == 1; self.dispatch_pass(ctx, BloomPhase::Blur, ping_pong, workgroup_size)?;
}
let blend_ping_pong = (1 + BLOOM_BLUR_PASSES) % 2 == 1;
self.dispatch_pass(ctx, BloomPhase::Blend, blend_ping_pong, workgroup_size)?;
} else {
self.dispatch_pass(ctx, BloomPhase::None, false, workgroup_size)?;
}
Ok(())
}
fn dispatch_pass(
&self,
ctx: &RenderContext,
phase: BloomPhase,
ping_pong: bool,
workgroup_size: (u32, u32),
) -> Result<()> {
let compute_pass = ctx.command_encoder.begin_compute_pass(Some(
&ComputePassDescriptor::new(Some("Effects Pass")).into(),
));
compute_pass.set_bind_group(0, self.bind_groups.get_bind_group(ping_pong)?, None)?;
if let Some(pipeline_key) = self.pipelines.get_bloom_pipeline(phase, ping_pong) {
compute_pass.set_pipeline(ctx.pipelines.compute.get(pipeline_key)?);
compute_pass.dispatch_workgroups(workgroup_size.0, Some(workgroup_size.1), Some(1));
}
compute_pass.end();
Ok(())
}
}