use std::borrow::Cow;
use crate::{
bind_group_layout::{
BindGroupLayoutCacheKey, BindGroupLayoutCacheKeyEntry, BindGroupLayoutKey,
},
bind_groups::{AwsmBindGroupError, BindGroupRecreateContext},
error::Result,
render_passes::RenderPassInitContext,
render_textures::RenderTextureFormats,
};
use awsm_renderer_core::{
bind_groups::{
BindGroupDescriptor, BindGroupEntry, BindGroupLayoutResource, BindGroupResource,
BufferBindingLayout, BufferBindingType, StorageTextureAccess, StorageTextureBindingLayout,
TextureBindingLayout,
},
buffers::BufferBinding,
texture::{TextureSampleType, TextureViewDimension},
};
#[derive(Default)]
pub struct EffectsBindGroups {
pub multisampled_bind_group_layout_key: BindGroupLayoutKey,
pub singlesampled_bind_group_layout_key: BindGroupLayoutKey,
_bind_group_a: Option<web_sys::GpuBindGroup>,
_bind_group_b: Option<web_sys::GpuBindGroup>,
}
impl EffectsBindGroups {
pub async fn new(ctx: &mut RenderPassInitContext<'_>) -> Result<Self> {
let singlesampled_bind_group_layout_cache_key =
bind_group_layout_cache_key(ctx.render_texture_formats, false);
let multisampled_bind_group_layout_cache_key =
bind_group_layout_cache_key(ctx.render_texture_formats, true);
let singlesampled_bind_group_layout_key = ctx
.bind_group_layouts
.get_key(ctx.gpu, singlesampled_bind_group_layout_cache_key)?;
let multisampled_bind_group_layout_key = ctx
.bind_group_layouts
.get_key(ctx.gpu, multisampled_bind_group_layout_cache_key)?;
Ok(Self {
multisampled_bind_group_layout_key,
singlesampled_bind_group_layout_key,
_bind_group_a: None,
_bind_group_b: None,
})
}
pub fn get_bind_group(
&self,
ping_pong: bool,
) -> std::result::Result<&web_sys::GpuBindGroup, AwsmBindGroupError> {
if !ping_pong {
self._bind_group_a
.as_ref()
.ok_or_else(|| AwsmBindGroupError::NotFound("Effects (A)".to_string()))
} else {
self._bind_group_b
.as_ref()
.ok_or_else(|| AwsmBindGroupError::NotFound("Effects (B)".to_string()))
}
}
pub fn recreate(&mut self, ctx: &BindGroupRecreateContext<'_>) -> Result<()> {
let mut entries = Vec::new();
entries.push(BindGroupEntry::new(
entries.len() as u32,
BindGroupResource::TextureView(Cow::Borrowed(&ctx.render_texture_views.composite)),
));
entries.push(BindGroupEntry::new(
entries.len() as u32,
BindGroupResource::Buffer(BufferBinding::new(&ctx.camera.gpu_buffer)),
));
entries.push(BindGroupEntry::new(
entries.len() as u32,
BindGroupResource::TextureView(Cow::Borrowed(&ctx.render_texture_views.depth)),
));
entries.push(BindGroupEntry::new(
entries.len() as u32,
BindGroupResource::TextureView(Cow::Borrowed(&ctx.render_texture_views.bloom)),
));
entries.push(BindGroupEntry::new(
entries.len() as u32,
BindGroupResource::TextureView(Cow::Borrowed(&ctx.render_texture_views.effects)),
));
let descriptor = BindGroupDescriptor::new(
ctx.bind_group_layouts
.get(if ctx.anti_aliasing.has_msaa_checked()? {
self.multisampled_bind_group_layout_key
} else {
self.singlesampled_bind_group_layout_key
})?,
Some("Effects (A)"),
entries,
);
self._bind_group_a = Some(ctx.gpu.create_bind_group(&descriptor.into()));
let mut entries = Vec::new();
entries.push(BindGroupEntry::new(
entries.len() as u32,
BindGroupResource::TextureView(Cow::Borrowed(&ctx.render_texture_views.composite)),
));
entries.push(BindGroupEntry::new(
entries.len() as u32,
BindGroupResource::Buffer(BufferBinding::new(&ctx.camera.gpu_buffer)),
));
entries.push(BindGroupEntry::new(
entries.len() as u32,
BindGroupResource::TextureView(Cow::Borrowed(&ctx.render_texture_views.depth)),
));
entries.push(BindGroupEntry::new(
entries.len() as u32,
BindGroupResource::TextureView(Cow::Borrowed(&ctx.render_texture_views.effects)),
));
entries.push(BindGroupEntry::new(
entries.len() as u32,
BindGroupResource::TextureView(Cow::Borrowed(&ctx.render_texture_views.bloom)),
));
let descriptor = BindGroupDescriptor::new(
ctx.bind_group_layouts
.get(if ctx.anti_aliasing.has_msaa_checked()? {
self.multisampled_bind_group_layout_key
} else {
self.singlesampled_bind_group_layout_key
})?,
Some("Effects (B)"),
entries,
);
self._bind_group_b = Some(ctx.gpu.create_bind_group(&descriptor.into()));
Ok(())
}
}
fn bind_group_layout_cache_key(
render_texture_formats: &RenderTextureFormats,
multisampled_geometry: bool,
) -> BindGroupLayoutCacheKey {
BindGroupLayoutCacheKey {
entries: vec![
BindGroupLayoutCacheKeyEntry {
resource: BindGroupLayoutResource::Texture(
TextureBindingLayout::new()
.with_view_dimension(TextureViewDimension::N2d)
.with_sample_type(TextureSampleType::UnfilterableFloat),
),
visibility_vertex: false,
visibility_fragment: false,
visibility_compute: true,
},
BindGroupLayoutCacheKeyEntry {
resource: BindGroupLayoutResource::Buffer(
BufferBindingLayout::new().with_binding_type(BufferBindingType::Uniform),
),
visibility_vertex: false,
visibility_fragment: false,
visibility_compute: true,
},
BindGroupLayoutCacheKeyEntry {
resource: BindGroupLayoutResource::Texture(
TextureBindingLayout::new()
.with_view_dimension(TextureViewDimension::N2d)
.with_sample_type(TextureSampleType::Depth)
.with_multisampled(multisampled_geometry),
),
visibility_vertex: false,
visibility_fragment: false,
visibility_compute: true,
},
BindGroupLayoutCacheKeyEntry {
resource: BindGroupLayoutResource::Texture(
TextureBindingLayout::new()
.with_view_dimension(TextureViewDimension::N2d)
.with_sample_type(TextureSampleType::UnfilterableFloat),
),
visibility_vertex: false,
visibility_fragment: false,
visibility_compute: true,
},
BindGroupLayoutCacheKeyEntry {
resource: BindGroupLayoutResource::StorageTexture(
StorageTextureBindingLayout::new(render_texture_formats.color)
.with_view_dimension(TextureViewDimension::N2d)
.with_access(StorageTextureAccess::WriteOnly),
),
visibility_vertex: false,
visibility_fragment: false,
visibility_compute: true,
},
],
}
}