pebble/wgpu/
render_bundle.rs1use crate::wgpu::{
2 backend::WGPUBackend, buffer::Buffer, buffers::BindGroup, material::RenderPipeline,
3 render_pass::IndexFormat, texture_format::TextureFormat,
4};
5
6pub struct RenderBundleEncoderBuilder<'a> {
20 label: Option<&'a str>,
21 color_formats: Vec<Option<TextureFormat>>,
25 depth_stencil_format: Option<TextureFormat>,
28 depth_read_only: bool,
30 stencil_read_only: bool,
32 sample_count: u32,
35}
36
37impl<'a> Default for RenderBundleEncoderBuilder<'a> {
38 fn default() -> Self {
39 Self {
40 label: None,
41 color_formats: Vec::new(),
42 depth_stencil_format: None,
43 depth_read_only: false,
44 stencil_read_only: false,
45 sample_count: 1,
46 }
47 }
48}
49
50impl<'a> RenderBundleEncoderBuilder<'a> {
51 pub fn new() -> Self {
52 Self::default()
53 }
54
55 pub fn label(mut self, label: impl Into<Option<&'a str>>) -> Self {
56 self.label = label.into();
57 self
58 }
59
60 pub fn color_formats(mut self, formats: Vec<Option<TextureFormat>>) -> Self {
61 self.color_formats = formats;
62 self
63 }
64
65 pub fn depth_stencil_format(mut self, format: TextureFormat) -> Self {
66 self.depth_stencil_format = Some(format);
67 self
68 }
69
70 pub fn depth_read_only(mut self, read_only: bool) -> Self {
71 self.depth_read_only = read_only;
72 self
73 }
74
75 pub fn stencil_read_only(mut self, read_only: bool) -> Self {
76 self.stencil_read_only = read_only;
77 self
78 }
79
80 pub fn sample_count(mut self, count: u32) -> Self {
83 self.sample_count = count;
84 self
85 }
86
87 fn validate(&self) {
91 if self.color_formats.is_empty() && self.depth_stencil_format.is_none() {
92 tracing::warn!(
93 "RenderBundleEncoderBuilder: no color_formats and no depth_stencil_format — \
94 this bundle has no attachments to execute against; did you forget to call \
95 .color_formats(...)?"
96 );
97 }
98 }
99
100 pub fn build(self, backend: &'a WGPUBackend) -> RenderBundleEncoder<'a> {
102 self.validate();
103
104 let color_formats: Vec<Option<wgpu::TextureFormat>> =
105 self.color_formats.iter().map(|f| f.map(Into::into)).collect();
106 let depth_stencil = self.depth_stencil_format.map(|format| wgpu::RenderBundleDepthStencil {
107 format: format.into(),
108 depth_read_only: self.depth_read_only,
109 stencil_read_only: self.stencil_read_only,
110 });
111 let raw = backend.device.create_render_bundle_encoder(&wgpu::RenderBundleEncoderDescriptor {
112 label: self.label,
113 color_formats: &color_formats,
114 depth_stencil,
115 sample_count: self.sample_count,
116 multiview: None,
117 });
118 RenderBundleEncoder::new(raw)
119 }
120}
121
122pub struct RenderBundleEncoder<'a> {
133 raw: wgpu::RenderBundleEncoder<'a>,
134}
135
136impl<'a> RenderBundleEncoder<'a> {
137 pub(crate) fn new(raw: wgpu::RenderBundleEncoder<'a>) -> Self {
138 Self { raw }
139 }
140
141 pub fn set_pipeline(&mut self, pipeline: &'a RenderPipeline) {
142 self.raw.set_pipeline(pipeline.raw());
143 }
144
145 pub fn set_bind_group(&mut self, index: u32, bind_group: &'a BindGroup, offsets: &[u32]) {
149 self.raw.set_bind_group(index, Some(bind_group.raw()), offsets);
150 }
151
152 pub fn set_vertex_buffer(&mut self, slot: u32, buffer: &'a Buffer) {
154 self.raw.set_vertex_buffer(slot, buffer.raw().slice(..));
155 }
156
157 pub fn set_index_buffer(&mut self, buffer: &'a Buffer, format: IndexFormat) {
159 self.raw.set_index_buffer(buffer.raw().slice(..), format.into());
160 }
161
162 pub fn draw(&mut self, vertices: std::ops::Range<u32>, instances: std::ops::Range<u32>) {
163 self.raw.draw(vertices, instances);
164 }
165
166 pub fn draw_indexed(
167 &mut self,
168 indices: std::ops::Range<u32>,
169 base_vertex: i32,
170 instances: std::ops::Range<u32>,
171 ) {
172 self.raw.draw_indexed(indices, base_vertex, instances);
173 }
174
175 pub fn finish(self, label: Option<&str>) -> RenderBundle {
177 RenderBundle(self.raw.finish(&wgpu::RenderBundleDescriptor { label }))
178 }
179}
180
181pub struct RenderBundle(wgpu::RenderBundle);
187
188impl RenderBundle {
189 pub(crate) fn raw(&self) -> &wgpu::RenderBundle {
190 &self.0
191 }
192}