use crate::error::Result;
use awsm_renderer_core::{
buffers::{BufferDescriptor, BufferUsage},
command::compute_pass::ComputePassDescriptor,
renderer::AwsmRendererWebGpu,
};
const INPUT_BYTE_SIZE: usize = 8; pub(super) const OUTPUT_BYTE_SIZE: usize = 12;
pub(super) struct PickerState {
pub in_flight: bool,
pub gpu_input_buffer: web_sys::GpuBuffer,
pub gpu_output_buffer: web_sys::GpuBuffer,
pub gpu_readback_buffer: web_sys::GpuBuffer,
pub gpu_input_raw: [u8; INPUT_BYTE_SIZE],
}
impl PickerState {
pub fn new(gpu: &AwsmRendererWebGpu) -> Result<Self> {
let gpu_input_buffer = gpu.create_buffer(
&BufferDescriptor::new(
Some("Picker Input"),
INPUT_BYTE_SIZE,
BufferUsage::new().with_uniform().with_copy_dst(),
)
.into(),
)?;
let gpu_output_buffer = gpu.create_buffer(
&BufferDescriptor::new(
Some("Picker Output"),
OUTPUT_BYTE_SIZE,
BufferUsage::new().with_storage().with_copy_src(),
)
.into(),
)?;
let gpu_readback_buffer = gpu.create_buffer(
&BufferDescriptor::new(
Some("Picker Output"),
OUTPUT_BYTE_SIZE,
BufferUsage::new().with_copy_dst().with_map_read(),
)
.into(),
)?;
Ok(Self {
in_flight: false,
gpu_input_buffer,
gpu_input_raw: [0; INPUT_BYTE_SIZE],
gpu_output_buffer,
gpu_readback_buffer,
})
}
pub fn begin_pick(
&mut self,
gpu: &AwsmRendererWebGpu,
bind_group: &web_sys::GpuBindGroup,
pipeline: &web_sys::GpuComputePipeline,
x: i32,
y: i32,
) -> Result<()> {
self.in_flight = true;
self.gpu_input_raw[..4].copy_from_slice(&x.to_le_bytes());
self.gpu_input_raw[4..8].copy_from_slice(&y.to_le_bytes());
gpu.write_buffer(
&self.gpu_input_buffer,
None,
self.gpu_input_raw.as_slice(),
None,
None,
)?;
let command_encoder = gpu.create_command_encoder(Some("Picker"));
let compute_pass = command_encoder
.begin_compute_pass(Some(&ComputePassDescriptor::new(Some("Picker")).into()));
compute_pass.set_bind_group(0u32, bind_group, None)?;
compute_pass.set_pipeline(pipeline);
compute_pass.dispatch_workgroups(1, Some(1), Some(1));
compute_pass.end();
command_encoder.copy_buffer_to_buffer(
&self.gpu_output_buffer,
0,
&self.gpu_readback_buffer,
0,
OUTPUT_BYTE_SIZE as u32,
)?;
gpu.submit_commands(&command_encoder.finish());
Ok(())
}
}