use std::borrow::Cow;
use awsm_renderer_core::bind_groups::{
BindGroupDescriptor, BindGroupEntry, BindGroupLayoutResource, BindGroupResource,
BufferBindingLayout, BufferBindingType, SamplerBindingLayout, SamplerBindingType,
TextureBindingLayout,
};
use awsm_renderer_core::buffers::BufferBinding;
use awsm_renderer_core::texture::{TextureSampleType, TextureViewDimension};
use indexmap::IndexSet;
use crate::bind_group_layout::{
BindGroupLayoutCacheKey, BindGroupLayoutCacheKeyEntry, BindGroupLayoutKey,
};
use crate::bind_groups::{AwsmBindGroupError, BindGroupRecreateContext};
use crate::error::Result;
use crate::render_passes::shared::material::bind_group::{TexturePoolDeps, TexturePoolVisibility};
use crate::render_passes::RenderPassInitContext;
use crate::textures::SamplerKey;
const MASKED_GROUP0_BUFFER_BINDINGS: u32 = 6;
pub struct GeometryMaskedBindGroup {
pub bind_group_layout_key: BindGroupLayoutKey,
pub texture_pool_arrays_len: u32,
pub texture_pool_sampler_keys: IndexSet<SamplerKey>,
_bind_group: Option<web_sys::GpuBindGroup>,
}
impl GeometryMaskedBindGroup {
pub async fn new(ctx: &mut RenderPassInitContext<'_>) -> Result<Self> {
let pool = TexturePoolDeps::new(ctx, TexturePoolVisibility::Render)?;
let bind_group_layout_key = build_layout_key(ctx, pool.arrays_len)?;
Ok(Self {
bind_group_layout_key,
texture_pool_arrays_len: pool.arrays_len,
texture_pool_sampler_keys: pool.sampler_keys,
_bind_group: None,
})
}
pub fn clone_because_texture_pool_changed(
&self,
ctx: &mut RenderPassInitContext<'_>,
) -> Result<Self> {
let pool = TexturePoolDeps::new(ctx, TexturePoolVisibility::Render)?;
let bind_group_layout_key = build_layout_key(ctx, pool.arrays_len)?;
Ok(Self {
bind_group_layout_key,
texture_pool_arrays_len: pool.arrays_len,
texture_pool_sampler_keys: pool.sampler_keys,
_bind_group: None,
})
}
pub fn recreate(&mut self, ctx: &BindGroupRecreateContext<'_>) -> Result<()> {
let mut entries = vec![
BindGroupEntry::new(
0,
BindGroupResource::Buffer(BufferBinding::new(&ctx.camera.gpu_buffer)),
),
BindGroupEntry::new(
1,
BindGroupResource::Buffer(BufferBinding::new(&ctx.frame_globals.gpu_buffer)),
),
BindGroupEntry::new(
2,
BindGroupResource::Buffer(BufferBinding::new(&ctx.materials.gpu_buffer)),
),
BindGroupEntry::new(
3,
BindGroupResource::Buffer(BufferBinding::new(
ctx.meshes.meta.material_gpu_buffer(),
)),
),
BindGroupEntry::new(
4,
BindGroupResource::Buffer(BufferBinding::new(
ctx.meshes.visibility_geometry_data_gpu_buffer(),
)),
),
BindGroupEntry::new(
5,
BindGroupResource::Buffer(BufferBinding::new(
&ctx.textures.texture_transforms_gpu_buffer,
)),
),
];
for view in ctx.textures.pool.texture_views() {
entries.push(BindGroupEntry::new(
entries.len() as u32,
BindGroupResource::TextureView(Cow::Borrowed(view)),
));
}
for sampler_key in self.texture_pool_sampler_keys.iter() {
let sampler = ctx.textures.get_sampler(*sampler_key)?;
entries.push(BindGroupEntry::new(
entries.len() as u32,
BindGroupResource::Sampler(sampler),
));
}
let descriptor = BindGroupDescriptor::new(
ctx.bind_group_layouts.get(self.bind_group_layout_key)?,
Some("Geometry Masked - Group 0"),
entries,
);
self._bind_group = Some(ctx.gpu.create_bind_group(&descriptor.into()));
Ok(())
}
pub fn get_bind_group(
&self,
) -> std::result::Result<&web_sys::GpuBindGroup, AwsmBindGroupError> {
self._bind_group
.as_ref()
.ok_or_else(|| AwsmBindGroupError::NotFound("Geometry masked group 0".to_string()))
}
}
fn build_layout_key(
ctx: &mut RenderPassInitContext<'_>,
arrays_len: u32,
) -> Result<BindGroupLayoutKey> {
let pool = TexturePoolDeps::new(ctx, TexturePoolVisibility::Render)?;
let samplers_len = pool.sampler_keys.len() as u32;
let uniform_vf = || BindGroupLayoutCacheKeyEntry {
resource: BindGroupLayoutResource::Buffer(
BufferBindingLayout::new().with_binding_type(BufferBindingType::Uniform),
),
visibility_vertex: true,
visibility_fragment: true,
visibility_compute: false,
};
let storage_f = || BindGroupLayoutCacheKeyEntry {
resource: BindGroupLayoutResource::Buffer(
BufferBindingLayout::new().with_binding_type(BufferBindingType::ReadOnlyStorage),
),
visibility_vertex: false,
visibility_fragment: true,
visibility_compute: false,
};
let mut entries = vec![
uniform_vf(), uniform_vf(), storage_f(), storage_f(), storage_f(), storage_f(), ];
debug_assert_eq!(entries.len() as u32, MASKED_GROUP0_BUFFER_BINDINGS);
for _ in 0..arrays_len {
entries.push(BindGroupLayoutCacheKeyEntry {
resource: BindGroupLayoutResource::Texture(
TextureBindingLayout::new()
.with_view_dimension(TextureViewDimension::N2dArray)
.with_sample_type(TextureSampleType::Float),
),
visibility_vertex: false,
visibility_fragment: true,
visibility_compute: false,
});
}
for _ in 0..samplers_len {
entries.push(BindGroupLayoutCacheKeyEntry {
resource: BindGroupLayoutResource::Sampler(
SamplerBindingLayout::new().with_binding_type(SamplerBindingType::Filtering),
),
visibility_vertex: false,
visibility_fragment: true,
visibility_compute: false,
});
}
Ok(ctx
.bind_group_layouts
.get_key(ctx.gpu, BindGroupLayoutCacheKey { entries })?)
}