use glam::{Vec2, Vec4};
use crate::{
backend::RenderState,
render::{bind_group::AsBindGroup, PipelineSet, PipelineSpec, PIPELINE_FILL},
};
use super::SpriteMaterial;
pub const SHADER_2D_DEFAULT: u32 = 0;
#[repr(C)]
#[derive(Debug, Clone, Copy, bytemuck::Pod, bytemuck::Zeroable)]
pub struct Vertex {
pub position: Vec2,
pub uv: Vec2,
}
#[repr(C)]
#[derive(Debug, Clone, Copy, bytemuck::Pod, bytemuck::Zeroable)]
pub struct Instance {
pub sprite_rect: Vec4,
pub matrix2: [f32; 4],
pub translation: Vec2,
pub color: [u8; 4],
pub _padding: [u8; 4],
}
pub struct PipelineBindGroup;
impl AsBindGroup for PipelineBindGroup {
fn bind_group_layout(device: &wgpu::Device) -> wgpu::BindGroupLayout
where
Self: Sized,
{
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: Some("fill_pipeline_bind_group_layout"),
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStages::VERTEX,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Storage { read_only: true },
has_dynamic_offset: false,
min_binding_size: None,
},
count: None,
},
wgpu::BindGroupLayoutEntry {
binding: 1,
visibility: wgpu::ShaderStages::VERTEX,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Storage { read_only: true },
has_dynamic_offset: false,
min_binding_size: None,
},
count: None,
},
],
})
}
fn as_bind_group(&self, render_state: &RenderState) -> wgpu::BindGroup {
let buffers = &render_state.buffers;
render_state
.device
.create_bind_group(&wgpu::BindGroupDescriptor {
label: None,
layout: &Self::bind_group_layout(&render_state.device),
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: buffers.get::<Vertex>().unwrap().as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 1,
resource: buffers.get::<Instance>().unwrap().as_entire_binding(),
},
],
})
}
}
pub fn register_fill_pipeline(render_state: &mut RenderState) {
render_state.init_buffer::<Vertex>(wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST);
render_state
.init_buffer::<Instance>(wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST);
render_state.register_shader(SHADER_2D_DEFAULT, wgpu::include_wgsl!("shaders/fill.wgsl"));
let spec: PipelineSpec<PipelineBindGroup, SpriteMaterial> = PipelineSpec {
shader_id: SHADER_2D_DEFAULT,
..Default::default()
};
let pipeline = spec.build(render_state);
let pipeline_set = PipelineSet {
pipeline,
pipeline_bind_group: Box::new(PipelineBindGroup),
};
render_state.pipelines.insert(PIPELINE_FILL, pipeline_set);
}