1use crate::{
2 binding_model::BindGroup,
3 id,
4 pipeline::RenderPipeline,
5 resource::{Buffer, QuerySet},
6};
7use wgt::{BufferAddress, BufferSize, Color};
8
9use std::sync::Arc;
10
11use super::{Rect, RenderBundle};
12
13#[doc(hidden)]
14#[derive(Clone, Copy, Debug)]
15#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
16pub enum RenderCommand {
17 SetBindGroup {
18 index: u32,
19 num_dynamic_offsets: usize,
20 bind_group_id: Option<id::BindGroupId>,
21 },
22 SetPipeline(id::RenderPipelineId),
23 SetIndexBuffer {
24 buffer_id: id::BufferId,
25 index_format: wgt::IndexFormat,
26 offset: BufferAddress,
27 size: Option<BufferSize>,
28 },
29 SetVertexBuffer {
30 slot: u32,
31 buffer_id: id::BufferId,
32 offset: BufferAddress,
33 size: Option<BufferSize>,
34 },
35 SetBlendConstant(Color),
36 SetStencilReference(u32),
37 SetViewport {
38 rect: Rect<f32>,
39 depth_min: f32,
41 depth_max: f32,
42 },
43 SetScissor(Rect<u32>),
44
45 SetPushConstant {
50 stages: wgt::ShaderStages,
52
53 offset: u32,
56
57 size_bytes: u32,
59
60 values_offset: Option<u32>,
71 },
72 Draw {
73 vertex_count: u32,
74 instance_count: u32,
75 first_vertex: u32,
76 first_instance: u32,
77 },
78 DrawIndexed {
79 index_count: u32,
80 instance_count: u32,
81 first_index: u32,
82 base_vertex: i32,
83 first_instance: u32,
84 },
85 DrawIndirect {
86 buffer_id: id::BufferId,
87 offset: BufferAddress,
88 count: u32,
89 indexed: bool,
90 },
91 MultiDrawIndirectCount {
92 buffer_id: id::BufferId,
93 offset: BufferAddress,
94 count_buffer_id: id::BufferId,
95 count_buffer_offset: BufferAddress,
96 max_count: u32,
97 indexed: bool,
98 },
99 PushDebugGroup {
100 color: u32,
101 len: usize,
102 },
103 PopDebugGroup,
104 InsertDebugMarker {
105 color: u32,
106 len: usize,
107 },
108 WriteTimestamp {
109 query_set_id: id::QuerySetId,
110 query_index: u32,
111 },
112 BeginOcclusionQuery {
113 query_index: u32,
114 },
115 EndOcclusionQuery,
116 BeginPipelineStatisticsQuery {
117 query_set_id: id::QuerySetId,
118 query_index: u32,
119 },
120 EndPipelineStatisticsQuery,
121 ExecuteBundle(id::RenderBundleId),
122}
123
124impl RenderCommand {
125 #[cfg(any(feature = "serde", feature = "replay"))]
127 pub fn resolve_render_command_ids(
128 hub: &crate::hub::Hub,
129 commands: &[RenderCommand],
130 ) -> Result<Vec<ArcRenderCommand>, super::RenderPassError> {
131 use super::{DrawKind, PassErrorScope, RenderPassError};
132
133 let buffers_guard = hub.buffers.read();
134 let bind_group_guard = hub.bind_groups.read();
135 let query_set_guard = hub.query_sets.read();
136 let pipelines_guard = hub.render_pipelines.read();
137 let render_bundles_guard = hub.render_bundles.read();
138
139 let resolved_commands: Vec<ArcRenderCommand> =
140 commands
141 .iter()
142 .map(|c| -> Result<ArcRenderCommand, RenderPassError> {
143 Ok(match *c {
144 RenderCommand::SetBindGroup {
145 index,
146 num_dynamic_offsets,
147 bind_group_id,
148 } => {
149 if bind_group_id.is_none() {
150 return Ok(ArcRenderCommand::SetBindGroup {
151 index,
152 num_dynamic_offsets,
153 bind_group: None,
154 });
155 }
156
157 let bind_group_id = bind_group_id.unwrap();
158 let bg = bind_group_guard.get(bind_group_id).get().map_err(|e| {
159 RenderPassError {
160 scope: PassErrorScope::SetBindGroup,
161 inner: e.into(),
162 }
163 })?;
164
165 ArcRenderCommand::SetBindGroup {
166 index,
167 num_dynamic_offsets,
168 bind_group: Some(bg),
169 }
170 }
171
172 RenderCommand::SetPipeline(pipeline_id) => ArcRenderCommand::SetPipeline(
173 pipelines_guard.get(pipeline_id).get().map_err(|e| {
174 RenderPassError {
175 scope: PassErrorScope::SetPipelineRender,
176 inner: e.into(),
177 }
178 })?,
179 ),
180
181 RenderCommand::SetPushConstant {
182 offset,
183 size_bytes,
184 values_offset,
185 stages,
186 } => ArcRenderCommand::SetPushConstant {
187 offset,
188 size_bytes,
189 values_offset,
190 stages,
191 },
192
193 RenderCommand::PushDebugGroup { color, len } => {
194 ArcRenderCommand::PushDebugGroup { color, len }
195 }
196
197 RenderCommand::PopDebugGroup => ArcRenderCommand::PopDebugGroup,
198
199 RenderCommand::InsertDebugMarker { color, len } => {
200 ArcRenderCommand::InsertDebugMarker { color, len }
201 }
202
203 RenderCommand::WriteTimestamp {
204 query_set_id,
205 query_index,
206 } => ArcRenderCommand::WriteTimestamp {
207 query_set: query_set_guard.get(query_set_id).get().map_err(|e| {
208 RenderPassError {
209 scope: PassErrorScope::WriteTimestamp,
210 inner: e.into(),
211 }
212 })?,
213 query_index,
214 },
215
216 RenderCommand::BeginPipelineStatisticsQuery {
217 query_set_id,
218 query_index,
219 } => ArcRenderCommand::BeginPipelineStatisticsQuery {
220 query_set: query_set_guard.get(query_set_id).get().map_err(|e| {
221 RenderPassError {
222 scope: PassErrorScope::BeginPipelineStatisticsQuery,
223 inner: e.into(),
224 }
225 })?,
226 query_index,
227 },
228
229 RenderCommand::EndPipelineStatisticsQuery => {
230 ArcRenderCommand::EndPipelineStatisticsQuery
231 }
232
233 RenderCommand::SetIndexBuffer {
234 buffer_id,
235 index_format,
236 offset,
237 size,
238 } => ArcRenderCommand::SetIndexBuffer {
239 buffer: buffers_guard.get(buffer_id).get().map_err(|e| {
240 RenderPassError {
241 scope: PassErrorScope::SetIndexBuffer,
242 inner: e.into(),
243 }
244 })?,
245 index_format,
246 offset,
247 size,
248 },
249
250 RenderCommand::SetVertexBuffer {
251 slot,
252 buffer_id,
253 offset,
254 size,
255 } => ArcRenderCommand::SetVertexBuffer {
256 slot,
257 buffer: buffers_guard.get(buffer_id).get().map_err(|e| {
258 RenderPassError {
259 scope: PassErrorScope::SetVertexBuffer,
260 inner: e.into(),
261 }
262 })?,
263 offset,
264 size,
265 },
266
267 RenderCommand::SetBlendConstant(color) => {
268 ArcRenderCommand::SetBlendConstant(color)
269 }
270
271 RenderCommand::SetStencilReference(reference) => {
272 ArcRenderCommand::SetStencilReference(reference)
273 }
274
275 RenderCommand::SetViewport {
276 rect,
277 depth_min,
278 depth_max,
279 } => ArcRenderCommand::SetViewport {
280 rect,
281 depth_min,
282 depth_max,
283 },
284
285 RenderCommand::SetScissor(scissor) => ArcRenderCommand::SetScissor(scissor),
286
287 RenderCommand::Draw {
288 vertex_count,
289 instance_count,
290 first_vertex,
291 first_instance,
292 } => ArcRenderCommand::Draw {
293 vertex_count,
294 instance_count,
295 first_vertex,
296 first_instance,
297 },
298
299 RenderCommand::DrawIndexed {
300 index_count,
301 instance_count,
302 first_index,
303 base_vertex,
304 first_instance,
305 } => ArcRenderCommand::DrawIndexed {
306 index_count,
307 instance_count,
308 first_index,
309 base_vertex,
310 first_instance,
311 },
312
313 RenderCommand::DrawIndirect {
314 buffer_id,
315 offset,
316 count,
317 indexed,
318 } => ArcRenderCommand::DrawIndirect {
319 buffer: buffers_guard.get(buffer_id).get().map_err(|e| {
320 RenderPassError {
321 scope: PassErrorScope::Draw {
322 kind: if count != 1 {
323 DrawKind::MultiDrawIndirect
324 } else {
325 DrawKind::DrawIndirect
326 },
327 indexed,
328 },
329 inner: e.into(),
330 }
331 })?,
332 offset,
333 count,
334 indexed,
335 },
336
337 RenderCommand::MultiDrawIndirectCount {
338 buffer_id,
339 offset,
340 count_buffer_id,
341 count_buffer_offset,
342 max_count,
343 indexed,
344 } => {
345 let scope = PassErrorScope::Draw {
346 kind: DrawKind::MultiDrawIndirectCount,
347 indexed,
348 };
349 ArcRenderCommand::MultiDrawIndirectCount {
350 buffer: buffers_guard.get(buffer_id).get().map_err(|e| {
351 RenderPassError {
352 scope,
353 inner: e.into(),
354 }
355 })?,
356 offset,
357 count_buffer: buffers_guard.get(count_buffer_id).get().map_err(
358 |e| RenderPassError {
359 scope,
360 inner: e.into(),
361 },
362 )?,
363 count_buffer_offset,
364 max_count,
365 indexed,
366 }
367 }
368
369 RenderCommand::BeginOcclusionQuery { query_index } => {
370 ArcRenderCommand::BeginOcclusionQuery { query_index }
371 }
372
373 RenderCommand::EndOcclusionQuery => ArcRenderCommand::EndOcclusionQuery,
374
375 RenderCommand::ExecuteBundle(bundle) => ArcRenderCommand::ExecuteBundle(
376 render_bundles_guard.get(bundle).get().map_err(|e| {
377 RenderPassError {
378 scope: PassErrorScope::ExecuteBundle,
379 inner: e.into(),
380 }
381 })?,
382 ),
383 })
384 })
385 .collect::<Result<Vec<_>, RenderPassError>>()?;
386 Ok(resolved_commands)
387 }
388}
389
390#[doc(hidden)]
392#[derive(Clone, Debug)]
393pub enum ArcRenderCommand {
394 SetBindGroup {
395 index: u32,
396 num_dynamic_offsets: usize,
397 bind_group: Option<Arc<BindGroup>>,
398 },
399 SetPipeline(Arc<RenderPipeline>),
400 SetIndexBuffer {
401 buffer: Arc<Buffer>,
402 index_format: wgt::IndexFormat,
403 offset: BufferAddress,
404 size: Option<BufferSize>,
405 },
406 SetVertexBuffer {
407 slot: u32,
408 buffer: Arc<Buffer>,
409 offset: BufferAddress,
410 size: Option<BufferSize>,
411 },
412 SetBlendConstant(Color),
413 SetStencilReference(u32),
414 SetViewport {
415 rect: Rect<f32>,
416 depth_min: f32,
417 depth_max: f32,
418 },
419 SetScissor(Rect<u32>),
420
421 SetPushConstant {
426 stages: wgt::ShaderStages,
428
429 offset: u32,
432
433 size_bytes: u32,
435
436 values_offset: Option<u32>,
447 },
448 Draw {
449 vertex_count: u32,
450 instance_count: u32,
451 first_vertex: u32,
452 first_instance: u32,
453 },
454 DrawIndexed {
455 index_count: u32,
456 instance_count: u32,
457 first_index: u32,
458 base_vertex: i32,
459 first_instance: u32,
460 },
461 DrawIndirect {
462 buffer: Arc<Buffer>,
463 offset: BufferAddress,
464 count: u32,
465 indexed: bool,
466 },
467 MultiDrawIndirectCount {
468 buffer: Arc<Buffer>,
469 offset: BufferAddress,
470 count_buffer: Arc<Buffer>,
471 count_buffer_offset: BufferAddress,
472 max_count: u32,
473 indexed: bool,
474 },
475 PushDebugGroup {
476 #[cfg_attr(target_os = "emscripten", allow(dead_code))]
477 color: u32,
478 len: usize,
479 },
480 PopDebugGroup,
481 InsertDebugMarker {
482 #[cfg_attr(target_os = "emscripten", allow(dead_code))]
483 color: u32,
484 len: usize,
485 },
486 WriteTimestamp {
487 query_set: Arc<QuerySet>,
488 query_index: u32,
489 },
490 BeginOcclusionQuery {
491 query_index: u32,
492 },
493 EndOcclusionQuery,
494 BeginPipelineStatisticsQuery {
495 query_set: Arc<QuerySet>,
496 query_index: u32,
497 },
498 EndPipelineStatisticsQuery,
499 ExecuteBundle(Arc<RenderBundle>),
500}