1use alloc::sync::Arc;
2
3use wgt::{BufferAddress, BufferSize, Color};
4
5use super::{DrawCommandFamily, Rect, RenderBundle};
6use crate::{
7 binding_model::BindGroup,
8 id,
9 pipeline::RenderPipeline,
10 resource::{Buffer, QuerySet},
11};
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 DrawMeshTasks {
86 group_count_x: u32,
87 group_count_y: u32,
88 group_count_z: u32,
89 },
90 DrawIndirect {
91 buffer_id: id::BufferId,
92 offset: BufferAddress,
93 count: u32,
94 family: DrawCommandFamily,
95 },
96 MultiDrawIndirectCount {
97 buffer_id: id::BufferId,
98 offset: BufferAddress,
99 count_buffer_id: id::BufferId,
100 count_buffer_offset: BufferAddress,
101 max_count: u32,
102 family: DrawCommandFamily,
103 },
104 PushDebugGroup {
105 color: u32,
106 len: usize,
107 },
108 PopDebugGroup,
109 InsertDebugMarker {
110 color: u32,
111 len: usize,
112 },
113 WriteTimestamp {
114 query_set_id: id::QuerySetId,
115 query_index: u32,
116 },
117 BeginOcclusionQuery {
118 query_index: u32,
119 },
120 EndOcclusionQuery,
121 BeginPipelineStatisticsQuery {
122 query_set_id: id::QuerySetId,
123 query_index: u32,
124 },
125 EndPipelineStatisticsQuery,
126 ExecuteBundle(id::RenderBundleId),
127}
128
129impl RenderCommand {
130 #[cfg(any(feature = "serde", feature = "replay"))]
132 pub fn resolve_render_command_ids(
133 hub: &crate::hub::Hub,
134 commands: &[RenderCommand],
135 ) -> Result<alloc::vec::Vec<ArcRenderCommand>, super::RenderPassError> {
136 use super::{DrawKind, PassErrorScope, RenderPassError};
137 use alloc::vec::Vec;
138
139 let buffers_guard = hub.buffers.read();
140 let bind_group_guard = hub.bind_groups.read();
141 let query_set_guard = hub.query_sets.read();
142 let pipelines_guard = hub.render_pipelines.read();
143 let render_bundles_guard = hub.render_bundles.read();
144
145 let resolved_commands: Vec<ArcRenderCommand> =
146 commands
147 .iter()
148 .map(|c| -> Result<ArcRenderCommand, RenderPassError> {
149 Ok(match *c {
150 RenderCommand::SetBindGroup {
151 index,
152 num_dynamic_offsets,
153 bind_group_id,
154 } => {
155 if bind_group_id.is_none() {
156 return Ok(ArcRenderCommand::SetBindGroup {
157 index,
158 num_dynamic_offsets,
159 bind_group: None,
160 });
161 }
162
163 let bind_group_id = bind_group_id.unwrap();
164 let bg = bind_group_guard.get(bind_group_id).get().map_err(|e| {
165 RenderPassError {
166 scope: PassErrorScope::SetBindGroup,
167 inner: e.into(),
168 }
169 })?;
170
171 ArcRenderCommand::SetBindGroup {
172 index,
173 num_dynamic_offsets,
174 bind_group: Some(bg),
175 }
176 }
177
178 RenderCommand::SetPipeline(pipeline_id) => ArcRenderCommand::SetPipeline(
179 pipelines_guard.get(pipeline_id).get().map_err(|e| {
180 RenderPassError {
181 scope: PassErrorScope::SetPipelineRender,
182 inner: e.into(),
183 }
184 })?,
185 ),
186
187 RenderCommand::SetPushConstant {
188 offset,
189 size_bytes,
190 values_offset,
191 stages,
192 } => ArcRenderCommand::SetPushConstant {
193 offset,
194 size_bytes,
195 values_offset,
196 stages,
197 },
198
199 RenderCommand::PushDebugGroup { color, len } => {
200 ArcRenderCommand::PushDebugGroup { color, len }
201 }
202
203 RenderCommand::PopDebugGroup => ArcRenderCommand::PopDebugGroup,
204
205 RenderCommand::InsertDebugMarker { color, len } => {
206 ArcRenderCommand::InsertDebugMarker { color, len }
207 }
208
209 RenderCommand::WriteTimestamp {
210 query_set_id,
211 query_index,
212 } => ArcRenderCommand::WriteTimestamp {
213 query_set: query_set_guard.get(query_set_id).get().map_err(|e| {
214 RenderPassError {
215 scope: PassErrorScope::WriteTimestamp,
216 inner: e.into(),
217 }
218 })?,
219 query_index,
220 },
221
222 RenderCommand::BeginPipelineStatisticsQuery {
223 query_set_id,
224 query_index,
225 } => ArcRenderCommand::BeginPipelineStatisticsQuery {
226 query_set: query_set_guard.get(query_set_id).get().map_err(|e| {
227 RenderPassError {
228 scope: PassErrorScope::BeginPipelineStatisticsQuery,
229 inner: e.into(),
230 }
231 })?,
232 query_index,
233 },
234
235 RenderCommand::EndPipelineStatisticsQuery => {
236 ArcRenderCommand::EndPipelineStatisticsQuery
237 }
238
239 RenderCommand::SetIndexBuffer {
240 buffer_id,
241 index_format,
242 offset,
243 size,
244 } => ArcRenderCommand::SetIndexBuffer {
245 buffer: buffers_guard.get(buffer_id).get().map_err(|e| {
246 RenderPassError {
247 scope: PassErrorScope::SetIndexBuffer,
248 inner: e.into(),
249 }
250 })?,
251 index_format,
252 offset,
253 size,
254 },
255
256 RenderCommand::SetVertexBuffer {
257 slot,
258 buffer_id,
259 offset,
260 size,
261 } => ArcRenderCommand::SetVertexBuffer {
262 slot,
263 buffer: buffers_guard.get(buffer_id).get().map_err(|e| {
264 RenderPassError {
265 scope: PassErrorScope::SetVertexBuffer,
266 inner: e.into(),
267 }
268 })?,
269 offset,
270 size,
271 },
272
273 RenderCommand::SetBlendConstant(color) => {
274 ArcRenderCommand::SetBlendConstant(color)
275 }
276
277 RenderCommand::SetStencilReference(reference) => {
278 ArcRenderCommand::SetStencilReference(reference)
279 }
280
281 RenderCommand::SetViewport {
282 rect,
283 depth_min,
284 depth_max,
285 } => ArcRenderCommand::SetViewport {
286 rect,
287 depth_min,
288 depth_max,
289 },
290
291 RenderCommand::SetScissor(scissor) => ArcRenderCommand::SetScissor(scissor),
292
293 RenderCommand::Draw {
294 vertex_count,
295 instance_count,
296 first_vertex,
297 first_instance,
298 } => ArcRenderCommand::Draw {
299 vertex_count,
300 instance_count,
301 first_vertex,
302 first_instance,
303 },
304
305 RenderCommand::DrawIndexed {
306 index_count,
307 instance_count,
308 first_index,
309 base_vertex,
310 first_instance,
311 } => ArcRenderCommand::DrawIndexed {
312 index_count,
313 instance_count,
314 first_index,
315 base_vertex,
316 first_instance,
317 },
318 RenderCommand::DrawMeshTasks {
319 group_count_x,
320 group_count_y,
321 group_count_z,
322 } => ArcRenderCommand::DrawMeshTasks {
323 group_count_x,
324 group_count_y,
325 group_count_z,
326 },
327
328 RenderCommand::DrawIndirect {
329 buffer_id,
330 offset,
331 count,
332 family,
333 } => ArcRenderCommand::DrawIndirect {
334 buffer: buffers_guard.get(buffer_id).get().map_err(|e| {
335 RenderPassError {
336 scope: PassErrorScope::Draw {
337 kind: if count != 1 {
338 DrawKind::MultiDrawIndirect
339 } else {
340 DrawKind::DrawIndirect
341 },
342 family,
343 },
344 inner: e.into(),
345 }
346 })?,
347 offset,
348 count,
349 family,
350
351 vertex_or_index_limit: 0,
352 instance_limit: 0,
353 },
354
355 RenderCommand::MultiDrawIndirectCount {
356 buffer_id,
357 offset,
358 count_buffer_id,
359 count_buffer_offset,
360 max_count,
361 family,
362 } => {
363 let scope = PassErrorScope::Draw {
364 kind: DrawKind::MultiDrawIndirectCount,
365 family,
366 };
367 ArcRenderCommand::MultiDrawIndirectCount {
368 buffer: buffers_guard.get(buffer_id).get().map_err(|e| {
369 RenderPassError {
370 scope,
371 inner: e.into(),
372 }
373 })?,
374 offset,
375 count_buffer: buffers_guard.get(count_buffer_id).get().map_err(
376 |e| RenderPassError {
377 scope,
378 inner: e.into(),
379 },
380 )?,
381 count_buffer_offset,
382 max_count,
383 family,
384 }
385 }
386
387 RenderCommand::BeginOcclusionQuery { query_index } => {
388 ArcRenderCommand::BeginOcclusionQuery { query_index }
389 }
390
391 RenderCommand::EndOcclusionQuery => ArcRenderCommand::EndOcclusionQuery,
392
393 RenderCommand::ExecuteBundle(bundle) => ArcRenderCommand::ExecuteBundle(
394 render_bundles_guard.get(bundle).get().map_err(|e| {
395 RenderPassError {
396 scope: PassErrorScope::ExecuteBundle,
397 inner: e.into(),
398 }
399 })?,
400 ),
401 })
402 })
403 .collect::<Result<Vec<_>, RenderPassError>>()?;
404 Ok(resolved_commands)
405 }
406}
407
408#[doc(hidden)]
421#[derive(Clone, Debug)]
422pub enum ArcRenderCommand {
423 SetBindGroup {
424 index: u32,
425 num_dynamic_offsets: usize,
426 bind_group: Option<Arc<BindGroup>>,
427 },
428 SetPipeline(Arc<RenderPipeline>),
429 SetIndexBuffer {
430 buffer: Arc<Buffer>,
431 index_format: wgt::IndexFormat,
432 offset: BufferAddress,
433 size: Option<BufferSize>,
434 },
435 SetVertexBuffer {
436 slot: u32,
437 buffer: Arc<Buffer>,
438 offset: BufferAddress,
439 size: Option<BufferSize>,
440 },
441 SetBlendConstant(Color),
442 SetStencilReference(u32),
443 SetViewport {
444 rect: Rect<f32>,
445 depth_min: f32,
446 depth_max: f32,
447 },
448 SetScissor(Rect<u32>),
449
450 SetPushConstant {
455 stages: wgt::ShaderStages,
457
458 offset: u32,
461
462 size_bytes: u32,
464
465 values_offset: Option<u32>,
476 },
477 Draw {
478 vertex_count: u32,
479 instance_count: u32,
480 first_vertex: u32,
481 first_instance: u32,
482 },
483 DrawIndexed {
484 index_count: u32,
485 instance_count: u32,
486 first_index: u32,
487 base_vertex: i32,
488 first_instance: u32,
489 },
490 DrawMeshTasks {
491 group_count_x: u32,
492 group_count_y: u32,
493 group_count_z: u32,
494 },
495 DrawIndirect {
496 buffer: Arc<Buffer>,
497 offset: BufferAddress,
498 count: u32,
499 family: DrawCommandFamily,
500
501 vertex_or_index_limit: u64,
503 instance_limit: u64,
505 },
506 MultiDrawIndirectCount {
507 buffer: Arc<Buffer>,
508 offset: BufferAddress,
509 count_buffer: Arc<Buffer>,
510 count_buffer_offset: BufferAddress,
511 max_count: u32,
512 family: DrawCommandFamily,
513 },
514 PushDebugGroup {
515 #[cfg_attr(not(any(feature = "serde", feature = "replay")), allow(dead_code))]
516 color: u32,
517 len: usize,
518 },
519 PopDebugGroup,
520 InsertDebugMarker {
521 #[cfg_attr(not(any(feature = "serde", feature = "replay")), allow(dead_code))]
522 color: u32,
523 len: usize,
524 },
525 WriteTimestamp {
526 query_set: Arc<QuerySet>,
527 query_index: u32,
528 },
529 BeginOcclusionQuery {
530 query_index: u32,
531 },
532 EndOcclusionQuery,
533 BeginPipelineStatisticsQuery {
534 query_set: Arc<QuerySet>,
535 query_index: u32,
536 },
537 EndPipelineStatisticsQuery,
538 ExecuteBundle(Arc<RenderBundle>),
539}