use std::borrow::Cow;
use awsm_renderer_core::bind_groups::{
BindGroupDescriptor, BindGroupEntry, BindGroupLayoutResource, BindGroupResource,
BufferBindingLayout, BufferBindingType, TextureBindingLayout,
};
use awsm_renderer_core::buffers::BufferBinding;
use awsm_renderer_core::texture::{TextureSampleType, TextureViewDimension};
use crate::bind_group_layout::{BindGroupLayoutCacheKey, BindGroupLayoutCacheKeyEntry};
use crate::bind_groups::{AwsmBindGroupError, BindGroupRecreateContext};
use crate::error::Result;
use crate::{bind_group_layout::BindGroupLayoutKey, render_passes::RenderPassInitContext};
pub struct MaterialClassifyBindGroups {
pub multisampled_bind_group_layout_key: BindGroupLayoutKey,
pub singlesampled_bind_group_layout_key: BindGroupLayoutKey,
bind_group: Option<web_sys::GpuBindGroup>,
}
impl MaterialClassifyBindGroups {
pub async fn new(ctx: &mut RenderPassInitContext<'_>) -> Result<Self> {
let multisampled_bind_group_layout_key = create_bind_group_layout_key(ctx, true).await?;
let singlesampled_bind_group_layout_key = create_bind_group_layout_key(ctx, false).await?;
Ok(Self {
multisampled_bind_group_layout_key,
singlesampled_bind_group_layout_key,
bind_group: None,
})
}
pub fn get_bind_group(
&self,
) -> std::result::Result<&web_sys::GpuBindGroup, AwsmBindGroupError> {
self.bind_group
.as_ref()
.ok_or_else(|| AwsmBindGroupError::NotFound("Material Classify".to_string()))
}
pub fn recreate(&mut self, ctx: &BindGroupRecreateContext<'_>) -> Result<()> {
let msaa = ctx.anti_aliasing.msaa_sample_count.is_some();
let layout_key = if msaa {
self.multisampled_bind_group_layout_key
} else {
self.singlesampled_bind_group_layout_key
};
let mut entries = vec![
BindGroupEntry::new(
0,
BindGroupResource::TextureView(Cow::Borrowed(
&ctx.render_texture_views.visibility_data,
)),
),
BindGroupEntry::new(
1,
BindGroupResource::Buffer(BufferBinding::new(
ctx.meshes.meta.material_gpu_buffer(),
)),
),
BindGroupEntry::new(
2,
BindGroupResource::Buffer(BufferBinding::new(&ctx.materials.gpu_buffer)),
),
BindGroupEntry::new(
3,
BindGroupResource::Buffer(BufferBinding::new(
&ctx.material_classify_buffers.buffer,
)),
),
];
if msaa {
if let (Some(edge_buffers), Some(edge_layout_uniform)) =
(ctx.material_edge_buffers, ctx.material_edge_layout_uniform)
{
entries.push(BindGroupEntry::new(
4,
BindGroupResource::Buffer(BufferBinding::new(&edge_buffers.args_buffer)),
));
entries.push(BindGroupEntry::new(
5,
BindGroupResource::Buffer(BufferBinding::new(edge_layout_uniform)),
));
entries.push(BindGroupEntry::new(
6,
BindGroupResource::Buffer(BufferBinding::new(&edge_buffers.data_buffer)),
));
entries.push(BindGroupEntry::new(
7,
BindGroupResource::TextureView(Cow::Borrowed(&ctx.render_texture_views.depth)),
));
entries.push(BindGroupEntry::new(
8,
BindGroupResource::Buffer(BufferBinding::new(&ctx.camera.gpu_buffer)),
));
entries.push(BindGroupEntry::new(
9,
BindGroupResource::TextureView(Cow::Borrowed(
&ctx.render_texture_views.normal_tangent,
)),
));
}
}
let descriptor = BindGroupDescriptor::new(
ctx.bind_group_layouts.get(layout_key)?,
Some("Material Classify"),
entries,
);
self.bind_group = Some(ctx.gpu.create_bind_group(&descriptor.into()));
Ok(())
}
}
fn edge_emit_supported(ctx: &RenderPassInitContext<'_>) -> bool {
crate::edge_resolve_supported(ctx.gpu)
}
async fn create_bind_group_layout_key(
ctx: &mut RenderPassInitContext<'_>,
multisampled_geometry: bool,
) -> Result<BindGroupLayoutKey> {
let mut entries = vec![
BindGroupLayoutCacheKeyEntry {
resource: BindGroupLayoutResource::Texture(
TextureBindingLayout::new()
.with_view_dimension(TextureViewDimension::N2d)
.with_sample_type(TextureSampleType::Uint)
.with_multisampled(multisampled_geometry),
),
visibility_vertex: false,
visibility_fragment: false,
visibility_compute: true,
},
BindGroupLayoutCacheKeyEntry {
resource: BindGroupLayoutResource::Buffer(
BufferBindingLayout::new().with_binding_type(BufferBindingType::ReadOnlyStorage),
),
visibility_vertex: false,
visibility_fragment: false,
visibility_compute: true,
},
BindGroupLayoutCacheKeyEntry {
resource: BindGroupLayoutResource::Buffer(
BufferBindingLayout::new().with_binding_type(BufferBindingType::ReadOnlyStorage),
),
visibility_vertex: false,
visibility_fragment: false,
visibility_compute: true,
},
BindGroupLayoutCacheKeyEntry {
resource: BindGroupLayoutResource::Buffer(
BufferBindingLayout::new().with_binding_type(BufferBindingType::Storage),
),
visibility_vertex: false,
visibility_fragment: false,
visibility_compute: true,
},
];
if multisampled_geometry && edge_emit_supported(ctx) {
entries.push(BindGroupLayoutCacheKeyEntry {
resource: BindGroupLayoutResource::Buffer(
BufferBindingLayout::new().with_binding_type(BufferBindingType::Storage),
),
visibility_vertex: false,
visibility_fragment: false,
visibility_compute: true,
});
entries.push(BindGroupLayoutCacheKeyEntry {
resource: BindGroupLayoutResource::Buffer(
BufferBindingLayout::new().with_binding_type(BufferBindingType::Uniform),
),
visibility_vertex: false,
visibility_fragment: false,
visibility_compute: true,
});
entries.push(BindGroupLayoutCacheKeyEntry {
resource: BindGroupLayoutResource::Buffer(
BufferBindingLayout::new().with_binding_type(BufferBindingType::Storage),
),
visibility_vertex: false,
visibility_fragment: false,
visibility_compute: true,
});
entries.push(BindGroupLayoutCacheKeyEntry {
resource: BindGroupLayoutResource::Texture(
TextureBindingLayout::new()
.with_view_dimension(TextureViewDimension::N2d)
.with_sample_type(TextureSampleType::Depth)
.with_multisampled(true),
),
visibility_vertex: false,
visibility_fragment: false,
visibility_compute: true,
});
entries.push(BindGroupLayoutCacheKeyEntry {
resource: BindGroupLayoutResource::Buffer(
BufferBindingLayout::new().with_binding_type(BufferBindingType::Uniform),
),
visibility_vertex: false,
visibility_fragment: false,
visibility_compute: true,
});
entries.push(BindGroupLayoutCacheKeyEntry {
resource: BindGroupLayoutResource::Texture(
TextureBindingLayout::new()
.with_view_dimension(TextureViewDimension::N2d)
.with_sample_type(TextureSampleType::UnfilterableFloat)
.with_multisampled(true),
),
visibility_vertex: false,
visibility_fragment: false,
visibility_compute: true,
});
}
Ok(ctx
.bind_group_layouts
.get_key(ctx.gpu, BindGroupLayoutCacheKey { entries })?)
}