use crate::anti_alias::AntiAliasing;
use crate::error::Result;
use crate::pipeline_layouts::PipelineLayoutCacheKey;
use crate::pipelines::compute_pipeline::{ComputePipelineCacheKey, ComputePipelineKey};
use crate::render_passes::hzb::{
bind_group::HzbBindGroups,
shader::cache_key::{ShaderCacheKeyHzbReduce, ShaderCacheKeyHzbSeed},
};
use crate::render_passes::RenderPassInitContext;
use crate::shaders::ShaderCacheKey;
pub struct HzbPipelines {
pub seed_msaa: Option<ComputePipelineKey>,
pub seed_single: Option<ComputePipelineKey>,
pub reduce: ComputePipelineKey,
}
pub struct HzbPrewarmDescriptors {
pub pipeline_cache_keys: Vec<ComputePipelineCacheKey>,
pub slot: Vec<HzbPipelineSlot>,
}
#[derive(Clone, Copy, Debug)]
pub enum HzbPipelineSlot {
SeedMsaa,
SeedSingle,
Reduce,
}
impl HzbPipelines {
pub async fn new(
ctx: &mut RenderPassInitContext<'_>,
bind_groups: &HzbBindGroups,
) -> Result<Self> {
ctx.shaders
.ensure_keys(ctx.gpu, Self::shader_cache_keys(ctx.anti_aliasing))
.await?;
let descs = Self::build_descriptors(ctx, bind_groups).await?;
let pipeline_keys = ctx
.pipelines
.compute
.ensure_keys(
ctx.gpu,
ctx.shaders,
ctx.pipeline_layouts,
descs.pipeline_cache_keys.clone(),
)
.await?;
Ok(Self::from_resolved(descs.slot, pipeline_keys))
}
pub fn shader_cache_keys(anti_aliasing: &AntiAliasing) -> Vec<ShaderCacheKey> {
let seed_msaa = match anti_aliasing.msaa_sample_count {
Some(4) => Some(4),
_ => None,
};
vec![
ShaderCacheKey::from(ShaderCacheKeyHzbSeed {
msaa_sample_count: seed_msaa,
}),
ShaderCacheKey::from(ShaderCacheKeyHzbReduce),
]
}
pub async fn build_descriptors(
ctx: &mut RenderPassInitContext<'_>,
bind_groups: &HzbBindGroups,
) -> Result<HzbPrewarmDescriptors> {
Self::build_descriptors_for_config(
ctx.gpu,
ctx.bind_group_layouts,
ctx.pipeline_layouts,
ctx.shaders,
bind_groups,
ctx.anti_aliasing,
)
.await
}
pub async fn build_descriptors_for_config(
gpu: &awsm_renderer_core::renderer::AwsmRendererWebGpu,
bind_group_layouts: &mut crate::bind_group_layout::BindGroupLayouts,
pipeline_layouts: &mut crate::pipeline_layouts::PipelineLayouts,
shaders: &mut crate::shaders::Shaders,
bind_groups: &HzbBindGroups,
anti_aliasing: &AntiAliasing,
) -> Result<HzbPrewarmDescriptors> {
let (seed_msaa, seed_layout_key, seed_slot) = match anti_aliasing.msaa_sample_count {
Some(4) => (
Some(4_u32),
bind_groups.seed_layout_key_msaa,
HzbPipelineSlot::SeedMsaa,
),
_ => (
None,
bind_groups.seed_layout_key_single,
HzbPipelineSlot::SeedSingle,
),
};
let seed_pipeline_layout = pipeline_layouts.get_key(
gpu,
bind_group_layouts,
PipelineLayoutCacheKey::new(vec![seed_layout_key]),
)?;
let reduce_pipeline_layout = pipeline_layouts.get_key(
gpu,
bind_group_layouts,
PipelineLayoutCacheKey::new(vec![bind_groups.reduce_layout_key]),
)?;
let seed_shader = shaders
.get_key(
gpu,
ShaderCacheKeyHzbSeed {
msaa_sample_count: seed_msaa,
},
)
.await?;
let reduce_shader = shaders.get_key(gpu, ShaderCacheKeyHzbReduce).await?;
Ok(HzbPrewarmDescriptors {
pipeline_cache_keys: vec![
ComputePipelineCacheKey::new(seed_shader, seed_pipeline_layout),
ComputePipelineCacheKey::new(reduce_shader, reduce_pipeline_layout),
],
slot: vec![seed_slot, HzbPipelineSlot::Reduce],
})
}
pub fn from_resolved(
slot: Vec<HzbPipelineSlot>,
pipeline_keys: Vec<ComputePipelineKey>,
) -> Self {
let mut seed_msaa = None;
let mut seed_single = None;
let mut reduce: Option<ComputePipelineKey> = None;
for (s, key) in slot.into_iter().zip(pipeline_keys) {
match s {
HzbPipelineSlot::SeedMsaa => seed_msaa = Some(key),
HzbPipelineSlot::SeedSingle => seed_single = Some(key),
HzbPipelineSlot::Reduce => reduce = Some(key),
}
}
Self {
seed_msaa,
seed_single,
reduce: reduce.expect("HZB reduce pipeline must be in initial build"),
}
}
pub fn merge_resolved(
&mut self,
slot: Vec<HzbPipelineSlot>,
pipeline_keys: Vec<ComputePipelineKey>,
) {
for (s, key) in slot.into_iter().zip(pipeline_keys) {
match s {
HzbPipelineSlot::SeedMsaa => self.seed_msaa = Some(key),
HzbPipelineSlot::SeedSingle => self.seed_single = Some(key),
HzbPipelineSlot::Reduce => self.reduce = key,
}
}
}
}