wgpu/util/
encoder.rs

1use std::ops::Range;
2
3use wgt::{BufferAddress, DynamicOffset, IndexFormat};
4
5use crate::{BindGroup, Buffer, BufferSlice, RenderBundleEncoder, RenderPass, RenderPipeline};
6
7/// Methods shared by [`RenderPass`] and [`RenderBundleEncoder`].
8pub trait RenderEncoder<'a> {
9    /// Sets the active bind group for a given bind group index. The bind group layout
10    /// in the active pipeline when any `draw()` function is called must match the layout of this bind group.
11    ///
12    /// If the bind group have dynamic offsets, provide them in order of their declaration.
13    fn set_bind_group(&mut self, index: u32, bind_group: &'a BindGroup, offsets: &[DynamicOffset]);
14
15    /// Sets the active render pipeline.
16    ///
17    /// Subsequent draw calls will exhibit the behavior defined by `pipeline`.
18    fn set_pipeline(&mut self, pipeline: &'a RenderPipeline);
19
20    /// Sets the active index buffer.
21    ///
22    /// Subsequent calls to [`draw_indexed`](RenderEncoder::draw_indexed) on this [`RenderEncoder`] will
23    /// use `buffer` as the source index buffer.
24    fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'a>, index_format: IndexFormat);
25
26    /// Assign a vertex buffer to a slot.
27    ///
28    /// Subsequent calls to [`draw`] and [`draw_indexed`] on this
29    /// [`RenderEncoder`] will use `buffer` as one of the source vertex buffers.
30    ///
31    /// The `slot` refers to the index of the matching descriptor in
32    /// [VertexState::buffers](crate::VertexState::buffers).
33    ///
34    /// [`draw`]: RenderEncoder::draw
35    /// [`draw_indexed`]: RenderEncoder::draw_indexed
36    fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>);
37
38    /// Draws primitives from the active vertex buffer(s).
39    ///
40    /// The active vertex buffers can be set with [`RenderEncoder::set_vertex_buffer`].
41    fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>);
42
43    /// Draws indexed primitives using the active index buffer and the active vertex buffers.
44    ///
45    /// The active index buffer can be set with [`RenderEncoder::set_index_buffer`], while the active
46    /// vertex buffers can be set with [`RenderEncoder::set_vertex_buffer`].
47    fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>);
48
49    /// Draws primitives from the active vertex buffer(s) based on the contents of the `indirect_buffer`.
50    ///
51    /// The active vertex buffers can be set with [`RenderEncoder::set_vertex_buffer`].
52    ///
53    /// The structure expected in `indirect_buffer` must conform to [`DrawIndirect`](crate::util::DrawIndirect).
54    fn draw_indirect(&mut self, indirect_buffer: &'a Buffer, indirect_offset: BufferAddress);
55
56    /// Draws indexed primitives using the active index buffer and the active vertex buffers,
57    /// based on the contents of the `indirect_buffer`.
58    ///
59    /// The active index buffer can be set with [`RenderEncoder::set_index_buffer`], while the active
60    /// vertex buffers can be set with [`RenderEncoder::set_vertex_buffer`].
61    ///
62    /// The structure expected in `indirect_buffer` must conform to [`DrawIndexedIndirect`](crate::util::DrawIndexedIndirect).
63    fn draw_indexed_indirect(
64        &mut self,
65        indirect_buffer: &'a Buffer,
66        indirect_offset: BufferAddress,
67    );
68
69    /// [`wgt::Features::PUSH_CONSTANTS`] must be enabled on the device in order to call this function.
70    ///
71    /// Set push constant data.
72    ///
73    /// Offset is measured in bytes, but must be a multiple of [`wgt::PUSH_CONSTANT_ALIGNMENT`].
74    ///
75    /// Data size must be a multiple of 4 and must be aligned to the 4s, so we take an array of u32.
76    /// For example, with an offset of 4 and an array of `[u32; 3]`, that will write to the range
77    /// of 4..16.
78    ///
79    /// For each byte in the range of push constant data written, the union of the stages of all push constant
80    /// ranges that covers that byte must be exactly `stages`. There's no good way of explaining this simply,
81    /// so here are some examples:
82    ///
83    /// ```text
84    /// For the given ranges:
85    /// - 0..4 Vertex
86    /// - 4..8 Fragment
87    /// ```
88    ///
89    /// You would need to upload this in two set_push_constants calls. First for the `Vertex` range, second for the `Fragment` range.
90    ///
91    /// ```text
92    /// For the given ranges:
93    /// - 0..8  Vertex
94    /// - 4..12 Fragment
95    /// ```
96    ///
97    /// You would need to upload this in three set_push_constants calls. First for the `Vertex` only range 0..4, second
98    /// for the `Vertex | Fragment` range 4..8, third for the `Fragment` range 8..12.
99    fn set_push_constants(&mut self, stages: wgt::ShaderStages, offset: u32, data: &[u8]);
100}
101
102impl<'a> RenderEncoder<'a> for RenderPass<'a> {
103    #[inline(always)]
104    fn set_bind_group(&mut self, index: u32, bind_group: &'a BindGroup, offsets: &[DynamicOffset]) {
105        Self::set_bind_group(self, index, bind_group, offsets);
106    }
107
108    #[inline(always)]
109    fn set_pipeline(&mut self, pipeline: &'a RenderPipeline) {
110        Self::set_pipeline(self, pipeline);
111    }
112
113    #[inline(always)]
114    fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'a>, index_format: IndexFormat) {
115        Self::set_index_buffer(self, buffer_slice, index_format);
116    }
117
118    #[inline(always)]
119    fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>) {
120        Self::set_vertex_buffer(self, slot, buffer_slice);
121    }
122
123    #[inline(always)]
124    fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
125        Self::draw(self, vertices, instances);
126    }
127
128    #[inline(always)]
129    fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {
130        Self::draw_indexed(self, indices, base_vertex, instances);
131    }
132
133    #[inline(always)]
134    fn draw_indirect(&mut self, indirect_buffer: &'a Buffer, indirect_offset: BufferAddress) {
135        Self::draw_indirect(self, indirect_buffer, indirect_offset);
136    }
137
138    #[inline(always)]
139    fn draw_indexed_indirect(
140        &mut self,
141        indirect_buffer: &'a Buffer,
142        indirect_offset: BufferAddress,
143    ) {
144        Self::draw_indexed_indirect(self, indirect_buffer, indirect_offset);
145    }
146
147    #[inline(always)]
148    fn set_push_constants(&mut self, stages: wgt::ShaderStages, offset: u32, data: &[u8]) {
149        Self::set_push_constants(self, stages, offset, data);
150    }
151}
152
153impl<'a> RenderEncoder<'a> for RenderBundleEncoder<'a> {
154    #[inline(always)]
155    fn set_bind_group(&mut self, index: u32, bind_group: &'a BindGroup, offsets: &[DynamicOffset]) {
156        Self::set_bind_group(self, index, bind_group, offsets);
157    }
158
159    #[inline(always)]
160    fn set_pipeline(&mut self, pipeline: &'a RenderPipeline) {
161        Self::set_pipeline(self, pipeline);
162    }
163
164    #[inline(always)]
165    fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'a>, index_format: IndexFormat) {
166        Self::set_index_buffer(self, buffer_slice, index_format);
167    }
168
169    #[inline(always)]
170    fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>) {
171        Self::set_vertex_buffer(self, slot, buffer_slice);
172    }
173
174    #[inline(always)]
175    fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
176        Self::draw(self, vertices, instances);
177    }
178
179    #[inline(always)]
180    fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {
181        Self::draw_indexed(self, indices, base_vertex, instances);
182    }
183
184    #[inline(always)]
185    fn draw_indirect(&mut self, indirect_buffer: &'a Buffer, indirect_offset: BufferAddress) {
186        Self::draw_indirect(self, indirect_buffer, indirect_offset);
187    }
188
189    #[inline(always)]
190    fn draw_indexed_indirect(
191        &mut self,
192        indirect_buffer: &'a Buffer,
193        indirect_offset: BufferAddress,
194    ) {
195        Self::draw_indexed_indirect(self, indirect_buffer, indirect_offset);
196    }
197
198    #[inline(always)]
199    fn set_push_constants(&mut self, stages: wgt::ShaderStages, offset: u32, data: &[u8]) {
200        Self::set_push_constants(self, stages, offset, data);
201    }
202}