use awsm_renderer_core::renderer::AwsmRendererWebGpu;
use crate::{
anti_alias::AntiAliasing,
error::Result,
pipeline_layouts::{PipelineLayoutCacheKey, PipelineLayoutKey, PipelineLayouts},
pipelines::{
compute_pipeline::{ComputePipelineCacheKey, ComputePipelineKey},
Pipelines,
},
post_process::PostProcessing,
render_passes::{
effects::{
bind_group::EffectsBindGroups,
shader::cache_key::{BloomPhase, ShaderCacheKeyEffects},
},
RenderPassInitContext,
},
render_textures::RenderTextureFormats,
shaders::Shaders,
};
pub const BLOOM_BLUR_PASSES: u32 = 3;
pub struct EffectsPipelines {
multisampled_pipeline_layout_key: PipelineLayoutKey,
singlesampled_pipeline_layout_key: PipelineLayoutKey,
no_bloom_pipeline: Option<ComputePipelineKey>,
bloom_extract_pipeline: Option<ComputePipelineKey>, bloom_blur_pipeline_a: Option<ComputePipelineKey>, bloom_blur_pipeline_b: Option<ComputePipelineKey>, bloom_blend_pipeline: Option<ComputePipelineKey>, }
impl EffectsPipelines {
pub async fn new(
ctx: &mut RenderPassInitContext<'_>,
bind_groups: &EffectsBindGroups,
) -> Result<Self> {
let singlesampled_pipeline_layout_cache_key =
PipelineLayoutCacheKey::new(vec![bind_groups.singlesampled_bind_group_layout_key]);
let multisampled_pipeline_layout_cache_key =
PipelineLayoutCacheKey::new(vec![bind_groups.multisampled_bind_group_layout_key]);
let singlesampled_pipeline_layout_key = ctx.pipeline_layouts.get_key(
ctx.gpu,
ctx.bind_group_layouts,
singlesampled_pipeline_layout_cache_key,
)?;
let multisampled_pipeline_layout_key = ctx.pipeline_layouts.get_key(
ctx.gpu,
ctx.bind_group_layouts,
multisampled_pipeline_layout_cache_key,
)?;
Ok(Self {
multisampled_pipeline_layout_key,
singlesampled_pipeline_layout_key,
no_bloom_pipeline: None,
bloom_extract_pipeline: None,
bloom_blur_pipeline_a: None,
bloom_blur_pipeline_b: None,
bloom_blend_pipeline: None,
})
}
pub fn get_bloom_pipeline(
&self,
phase: BloomPhase,
ping_pong: bool,
) -> Option<ComputePipelineKey> {
match phase {
BloomPhase::None => self.no_bloom_pipeline,
BloomPhase::Extract => self.bloom_extract_pipeline,
BloomPhase::Blur => {
if ping_pong {
self.bloom_blur_pipeline_b
} else {
self.bloom_blur_pipeline_a
}
}
BloomPhase::Blend => self.bloom_blend_pipeline,
}
}
pub async fn set_render_pipeline_keys(
&mut self,
anti_aliasing: &AntiAliasing,
post_processing: &PostProcessing,
gpu: &AwsmRendererWebGpu,
shaders: &mut Shaders,
pipelines: &mut Pipelines,
pipeline_layouts: &PipelineLayouts,
render_texture_formats: &RenderTextureFormats,
) -> Result<()> {
let multisampled_geometry = anti_aliasing.has_msaa_checked()?;
self.no_bloom_pipeline = Some(
self.create_pipeline(
anti_aliasing,
post_processing,
gpu,
shaders,
pipelines,
pipeline_layouts,
render_texture_formats,
BloomPhase::None,
false,
multisampled_geometry,
)
.await?,
);
self.bloom_extract_pipeline = Some(
self.create_pipeline(
anti_aliasing,
post_processing,
gpu,
shaders,
pipelines,
pipeline_layouts,
render_texture_formats,
BloomPhase::Extract,
false,
multisampled_geometry,
)
.await?,
);
self.bloom_blur_pipeline_a = Some(
self.create_pipeline(
anti_aliasing,
post_processing,
gpu,
shaders,
pipelines,
pipeline_layouts,
render_texture_formats,
BloomPhase::Blur,
false,
multisampled_geometry,
)
.await?,
);
self.bloom_blur_pipeline_b = Some(
self.create_pipeline(
anti_aliasing,
post_processing,
gpu,
shaders,
pipelines,
pipeline_layouts,
render_texture_formats,
BloomPhase::Blur,
true,
multisampled_geometry,
)
.await?,
);
let blend_ping_pong = (1 + BLOOM_BLUR_PASSES) % 2 == 1;
self.bloom_blend_pipeline = Some(
self.create_pipeline(
anti_aliasing,
post_processing,
gpu,
shaders,
pipelines,
pipeline_layouts,
render_texture_formats,
BloomPhase::Blend,
blend_ping_pong,
multisampled_geometry,
)
.await?,
);
Ok(())
}
#[allow(clippy::too_many_arguments)]
async fn create_pipeline(
&self,
anti_aliasing: &AntiAliasing,
_post_processing: &PostProcessing,
gpu: &AwsmRendererWebGpu,
shaders: &mut Shaders,
pipelines: &mut Pipelines,
pipeline_layouts: &PipelineLayouts,
_render_texture_formats: &RenderTextureFormats,
bloom_phase: BloomPhase,
ping_pong: bool,
multisampled_geometry: bool,
) -> Result<ComputePipelineKey> {
let shader_cache_key = ShaderCacheKeyEffects {
smaa_anti_alias: anti_aliasing.smaa,
bloom_phase,
dof: _post_processing.dof,
ping_pong,
multisampled_geometry,
};
let shader_key = shaders.get_key(gpu, shader_cache_key).await?;
let compute_pipeline_cache_key = ComputePipelineCacheKey::new(
shader_key,
if multisampled_geometry {
self.multisampled_pipeline_layout_key
} else {
self.singlesampled_pipeline_layout_key
},
);
Ok(pipelines
.compute
.get_key(gpu, shaders, pipeline_layouts, compute_pipeline_cache_key)
.await?)
}
}