easygpu_lyon/
pipeline.rs

1use std::marker::PhantomData;
2use std::ops::Deref;
3
4use bytemuck::{Pod, Zeroable};
5use easygpu::prelude::*;
6use easygpu::wgpu::TextureFormat;
7
8/// A pipeline for rendering shapes.
9pub struct LyonPipeline<T> {
10    pipeline: PipelineCore,
11    _phantom: PhantomData<T>,
12}
13
14#[repr(C)]
15#[derive(Copy, Clone, Pod, Zeroable)]
16/// The uniforms for the shader.
17pub struct Uniforms {
18    /// The orthographic projection matrix
19    pub ortho: [f32; 16],
20    /// The transformation matrix
21    pub transform: [f32; 16],
22}
23
24pub trait VertexShaderSource {
25    fn shader() -> &'static [u8];
26
27    fn sampler_format() -> TextureFormat;
28}
29
30pub struct Srgb;
31pub struct Normal;
32
33impl VertexShaderSource for Srgb {
34    fn shader() -> &'static [u8] {
35        include_bytes!("shaders/shape-srgb.vert.spv")
36    }
37
38    fn sampler_format() -> TextureFormat {
39        TextureFormat::Bgra8UnormSrgb
40    }
41}
42
43impl VertexShaderSource for Normal {
44    fn shader() -> &'static [u8] {
45        include_bytes!("shaders/shape.vert.spv")
46    }
47
48    fn sampler_format() -> TextureFormat {
49        TextureFormat::Bgra8Unorm
50    }
51}
52
53impl<'a, T> AbstractPipeline<'a> for LyonPipeline<T>
54where
55    T: VertexShaderSource,
56{
57    type PrepareContext = ScreenTransformation<f32>;
58    type Uniforms = Uniforms;
59
60    fn description() -> PipelineDescription<'a> {
61        PipelineDescription {
62            vertex_layout: &[VertexFormat::Float3, VertexFormat::UByte4],
63            pipeline_layout: &[Set(&[Binding {
64                binding: BindingType::UniformBuffer,
65                stage: ShaderStages::VERTEX,
66            }])],
67            vertex_shader: T::shader(),
68            fragment_shader: include_bytes!("shaders/shape.frag.spv"),
69        }
70    }
71
72    fn setup(pipeline: Pipeline, dev: &Device) -> Self {
73        let transform = ScreenTransformation::identity().to_array();
74        let ortho = ScreenTransformation::identity().to_array();
75        let uniforms = dev.create_uniform_buffer(&[self::Uniforms { ortho, transform }]);
76        let bindings = dev.create_binding_group(&pipeline.layout.sets[0], &[&uniforms]);
77
78        Self {
79            pipeline: PipelineCore {
80                pipeline,
81                uniforms,
82                bindings,
83            },
84            _phantom: PhantomData::default(),
85        }
86    }
87
88    fn prepare(
89        &'a self,
90        ortho: Self::PrepareContext,
91    ) -> Option<(&'a UniformBuffer, Vec<Self::Uniforms>)> {
92        let ortho = ortho.to_array();
93        let transform = ScreenTransformation::identity().to_array();
94        Some((
95            &self.pipeline.uniforms,
96            vec![self::Uniforms { transform, ortho }],
97        ))
98    }
99}
100
101impl<T> Deref for LyonPipeline<T> {
102    type Target = PipelineCore;
103
104    fn deref(&self) -> &Self::Target {
105        &self.pipeline
106    }
107}