srs2dge_core/frame/
render_pass.rs

1use crate::{
2    buffer::{index::Index, IndexBuffer, Vertex, VertexBuffer},
3    shader::Shader,
4};
5use std::{marker::PhantomData, ops::Range};
6use wgpu::{BindGroup, TextureFormat};
7
8//
9
10pub struct RenderPass<'e, Sv = (), Bv = (), Si = (), Bi = (), const PIPELINE_BOUND: bool = false> {
11    pub(crate) inner: wgpu::RenderPass<'e>,
12    pub(crate) format: TextureFormat,
13
14    _p: PhantomData<(Sv, Bv, Si, Bi)>,
15}
16
17//
18
19impl<'e, Sv, Bv, Si, Bi, const PIPELINE_BOUND: bool>
20    RenderPass<'e, Sv, Bv, Si, Bi, PIPELINE_BOUND>
21{
22    pub fn bind_vbo<'b, T>(
23        mut self,
24        buffer: &'b VertexBuffer<T>,
25        // slot: u32,
26    ) -> RenderPass<'e, Sv, T, Si, Bi, PIPELINE_BOUND>
27    where
28        'b: 'e,
29        T: Vertex + 'static,
30    {
31        self.inner.set_vertex_buffer(0, buffer.inner().slice(..));
32        self.pass()
33    }
34
35    pub fn bind_ibo<'b, T>(
36        mut self,
37        buffer: &'b IndexBuffer<T>,
38    ) -> RenderPass<'e, Sv, Bv, Si, T, PIPELINE_BOUND>
39    where
40        'b: 'e,
41        T: Index + 'static,
42    {
43        self.inner
44            .set_index_buffer(buffer.inner().slice(..), T::FORMAT);
45        self.pass()
46    }
47
48    pub fn bind_shader<'s, V, I>(
49        mut self,
50        shader: &'s Shader<V, I>,
51    ) -> RenderPass<'e, V, Bv, I, Bi, true>
52    where
53        's: 'e,
54        V: Vertex + 'static,
55        I: Index + 'static,
56    {
57        if self.format != shader.format {
58            panic!("Shader output incompatible with this render target");
59        } else {
60            self.inner.set_pipeline(&shader.pipeline);
61        }
62        self.pass()
63    }
64
65    pub fn bind_group<'g>(mut self, bind_group: &'g BindGroup) -> Self
66    where
67        'g: 'e,
68    {
69        self.inner.set_bind_group(0, bind_group, &[]);
70        self.pass()
71    }
72
73    pub fn done(self) -> RenderPass<'e> {
74        self.pass()
75    }
76
77    pub(crate) fn new(inner: wgpu::RenderPass<'e>, format: TextureFormat) -> Self {
78        Self {
79            inner,
80            format,
81            _p: PhantomData::default(),
82        }
83    }
84
85    fn pass<Svn, Bvn, Sin, Bin, const N: bool>(self) -> RenderPass<'e, Svn, Bvn, Sin, Bin, N> {
86        RenderPass {
87            inner: self.inner,
88            format: self.format,
89            _p: PhantomData::default(),
90        }
91    }
92}
93
94// implement for all renderpasses where buffers match shaders and shader is bound
95impl<'e, V, I> RenderPass<'e, V, V, I, I, true> {
96    pub fn draw(mut self, vertices: Range<u32>, instances: Range<u32>) -> Self {
97        self.inner.draw(vertices, instances);
98        self
99    }
100
101    pub fn draw_indexed(
102        mut self,
103        indices: Range<u32>,
104        base_vertex: i32,
105        instances: Range<u32>,
106    ) -> Self {
107        self.inner.draw_indexed(indices, base_vertex, instances);
108        self
109    }
110
111    // TODO:
112    /* pub fn draw_indirect(&mut self, vertices: Range<u32>, instances: Range<u32>) {
113        self.inner.draw_indirect(vertices, instances)
114    }
115
116    pub fn draw_indirect_indexed(&mut self, vertices: Range<u32>, instances: Range<u32>) {
117        self.inner.draw(vertices, instances)
118    } */
119}