use awsm_renderer_core::bind_groups::{
BindGroupDescriptor, BindGroupEntry, BindGroupLayoutResource, BindGroupResource,
BufferBindingLayout, BufferBindingType,
};
use awsm_renderer_core::buffers::BufferBinding;
use awsm_renderer_core::renderer::AwsmRendererWebGpu;
use crate::bind_group_layout::{
BindGroupLayoutCacheKey, BindGroupLayoutCacheKeyEntry, BindGroupLayoutKey, BindGroupLayouts,
};
use crate::bind_groups::AwsmBindGroupError;
use crate::error::Result;
use crate::render_passes::cluster_lod::buffers::ClusterLodBuffers;
use crate::render_passes::RenderPassInitContext;
#[derive(Clone)]
pub struct ClusterCutBindGroups {
pub layout_key: BindGroupLayoutKey,
bind_group: Option<web_sys::GpuBindGroup>,
paging: bool,
}
impl ClusterCutBindGroups {
pub fn new(ctx: &mut RenderPassInitContext<'_>) -> Result<Self> {
let paging = ctx.features.cluster_paging;
let compute_only = |resource| BindGroupLayoutCacheKeyEntry {
resource,
visibility_vertex: false,
visibility_fragment: false,
visibility_compute: true,
};
let mut entries = vec![
compute_only(BindGroupLayoutResource::Buffer(
BufferBindingLayout::new().with_binding_type(BufferBindingType::ReadOnlyStorage),
)),
compute_only(BindGroupLayoutResource::Buffer(
BufferBindingLayout::new().with_binding_type(BufferBindingType::Storage),
)),
compute_only(BindGroupLayoutResource::Buffer(
BufferBindingLayout::new().with_binding_type(BufferBindingType::Uniform),
)),
];
if paging {
entries.push(compute_only(BindGroupLayoutResource::Buffer(
BufferBindingLayout::new().with_binding_type(BufferBindingType::ReadOnlyStorage),
)));
}
let layout_key = ctx
.bind_group_layouts
.get_key(ctx.gpu, BindGroupLayoutCacheKey { entries })?;
Ok(Self {
layout_key,
bind_group: None,
paging,
})
}
pub fn get_bind_group(
&self,
) -> std::result::Result<&web_sys::GpuBindGroup, AwsmBindGroupError> {
self.bind_group
.as_ref()
.ok_or_else(|| AwsmBindGroupError::NotFound("ClusterCut".to_string()))
}
pub fn recreate(
&mut self,
gpu: &AwsmRendererWebGpu,
layouts: &BindGroupLayouts,
buffers: &ClusterLodBuffers,
) -> Result<()> {
let mut entries = vec![
BindGroupEntry::new(
0,
BindGroupResource::Buffer(BufferBinding::new(&buffers.pages_buffer)),
),
BindGroupEntry::new(
1,
BindGroupResource::Buffer(BufferBinding::new(&buffers.selected_buffer)),
),
BindGroupEntry::new(
2,
BindGroupResource::Buffer(BufferBinding::new(&buffers.params_buffer)),
),
];
if self.paging {
match buffers.resident_buffer.as_ref() {
Some(resident) => entries.push(BindGroupEntry::new(
3,
BindGroupResource::Buffer(BufferBinding::new(resident)),
)),
None => return Ok(()),
}
}
let descriptor =
BindGroupDescriptor::new(layouts.get(self.layout_key)?, Some("ClusterCut"), entries);
self.bind_group = Some(gpu.create_bind_group(&descriptor.into()));
Ok(())
}
}
#[derive(Clone)]
pub struct ClusterCompactionBindGroups {
pub layout_key: BindGroupLayoutKey,
bind_group: Option<web_sys::GpuBindGroup>,
}
impl ClusterCompactionBindGroups {
pub fn new(ctx: &mut RenderPassInitContext<'_>) -> Result<Self> {
let compute_only = |resource| BindGroupLayoutCacheKeyEntry {
resource,
visibility_vertex: false,
visibility_fragment: false,
visibility_compute: true,
};
let storage_ro = || {
BindGroupLayoutResource::Buffer(
BufferBindingLayout::new().with_binding_type(BufferBindingType::ReadOnlyStorage),
)
};
let storage_rw = || {
BindGroupLayoutResource::Buffer(
BufferBindingLayout::new().with_binding_type(BufferBindingType::Storage),
)
};
let entries = vec![
compute_only(storage_ro()), compute_only(storage_ro()), compute_only(storage_ro()), compute_only(storage_rw()), compute_only(storage_rw()), compute_only(BindGroupLayoutResource::Buffer(
BufferBindingLayout::new().with_binding_type(BufferBindingType::Uniform),
)), ];
let layout_key = ctx
.bind_group_layouts
.get_key(ctx.gpu, BindGroupLayoutCacheKey { entries })?;
Ok(Self {
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("ClusterCompaction".to_string()))
}
pub fn recreate(
&mut self,
gpu: &AwsmRendererWebGpu,
layouts: &BindGroupLayouts,
buffers: &ClusterLodBuffers,
) -> Result<()> {
let buf = |i, b| BindGroupEntry::new(i, BindGroupResource::Buffer(BufferBinding::new(b)));
let entries = vec![
buf(0, &buffers.pages_buffer),
buf(1, &buffers.selected_buffer),
buf(2, &buffers.source_indices_buffer),
buf(3, &buffers.compacted_indices_buffer),
buf(4, &buffers.draw_args_buffer),
buf(5, &buffers.params_buffer),
];
let descriptor = BindGroupDescriptor::new(
layouts.get(self.layout_key)?,
Some("ClusterCompaction"),
entries,
);
self.bind_group = Some(gpu.create_bind_group(&descriptor.into()));
Ok(())
}
}