pittore/render/render2d/
pipeline.rs

1use glam::{Vec2, Vec4};
2
3use crate::{
4    backend::RenderState,
5    render::{bind_group::AsBindGroup, PipelineSet, PipelineSpec, PIPELINE_FILL},
6};
7
8use super::SpriteMaterial;
9
10pub const SHADER_2D_DEFAULT: u32 = 0;
11
12#[repr(C)]
13#[derive(Debug, Clone, Copy, bytemuck::Pod, bytemuck::Zeroable)]
14pub struct Vertex {
15    pub position: Vec2,
16    pub uv: Vec2,
17}
18
19#[repr(C)]
20#[derive(Debug, Clone, Copy, bytemuck::Pod, bytemuck::Zeroable)]
21pub struct Instance {
22    pub sprite_rect: Vec4,
23    pub matrix2: [f32; 4],
24    pub translation: Vec2,
25    pub color: [u8; 4],
26    pub _padding: [u8; 4],
27}
28
29pub struct PipelineBindGroup;
30
31impl AsBindGroup for PipelineBindGroup {
32    fn bind_group_layout(device: &wgpu::Device) -> wgpu::BindGroupLayout
33    where
34        Self: Sized,
35    {
36        device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
37            label: Some("fill_pipeline_bind_group_layout"),
38            entries: &[
39                wgpu::BindGroupLayoutEntry {
40                    binding: 0,
41                    visibility: wgpu::ShaderStages::VERTEX,
42                    ty: wgpu::BindingType::Buffer {
43                        ty: wgpu::BufferBindingType::Storage { read_only: true },
44                        has_dynamic_offset: false,
45                        min_binding_size: None,
46                    },
47                    count: None,
48                },
49                wgpu::BindGroupLayoutEntry {
50                    binding: 1,
51                    visibility: wgpu::ShaderStages::VERTEX,
52                    ty: wgpu::BindingType::Buffer {
53                        ty: wgpu::BufferBindingType::Storage { read_only: true },
54                        has_dynamic_offset: false,
55                        min_binding_size: None,
56                    },
57                    count: None,
58                },
59            ],
60        })
61    }
62
63    fn as_bind_group(&self, render_state: &RenderState) -> wgpu::BindGroup {
64        let buffers = &render_state.buffers;
65
66        render_state
67            .device
68            .create_bind_group(&wgpu::BindGroupDescriptor {
69                label: None,
70                layout: &Self::bind_group_layout(&render_state.device),
71                entries: &[
72                    wgpu::BindGroupEntry {
73                        binding: 0,
74                        resource: buffers.get::<Vertex>().unwrap().as_entire_binding(),
75                    },
76                    wgpu::BindGroupEntry {
77                        binding: 1,
78                        resource: buffers.get::<Instance>().unwrap().as_entire_binding(),
79                    },
80                ],
81            })
82    }
83}
84
85pub fn register_fill_pipeline(render_state: &mut RenderState) {
86    render_state.init_buffer::<Vertex>(wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST);
87    render_state
88        .init_buffer::<Instance>(wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST);
89
90    render_state.register_shader(SHADER_2D_DEFAULT, wgpu::include_wgsl!("shaders/fill.wgsl"));
91
92    let spec: PipelineSpec<PipelineBindGroup, SpriteMaterial> = PipelineSpec {
93        shader_id: SHADER_2D_DEFAULT,
94        ..Default::default()
95    };
96    let pipeline = spec.build(render_state);
97
98    let pipeline_set = PipelineSet {
99        pipeline,
100        pipeline_bind_group: Box::new(PipelineBindGroup),
101    };
102
103    render_state.pipelines.insert(PIPELINE_FILL, pipeline_set);
104}