1use alloc::sync::Arc;
2
3use wgt::{BufferAddress, BufferSize, Color};
4
5use super::{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 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<alloc::vec::Vec<ArcRenderCommand>, super::RenderPassError> {
131 use super::{DrawKind, PassErrorScope, RenderPassError};
132 use alloc::vec::Vec;
133
134 let buffers_guard = hub.buffers.read();
135 let bind_group_guard = hub.bind_groups.read();
136 let query_set_guard = hub.query_sets.read();
137 let pipelines_guard = hub.render_pipelines.read();
138 let render_bundles_guard = hub.render_bundles.read();
139
140 let resolved_commands: Vec<ArcRenderCommand> =
141 commands
142 .iter()
143 .map(|c| -> Result<ArcRenderCommand, RenderPassError> {
144 Ok(match *c {
145 RenderCommand::SetBindGroup {
146 index,
147 num_dynamic_offsets,
148 bind_group_id,
149 } => {
150 if bind_group_id.is_none() {
151 return Ok(ArcRenderCommand::SetBindGroup {
152 index,
153 num_dynamic_offsets,
154 bind_group: None,
155 });
156 }
157
158 let bind_group_id = bind_group_id.unwrap();
159 let bg = bind_group_guard.get(bind_group_id).get().map_err(|e| {
160 RenderPassError {
161 scope: PassErrorScope::SetBindGroup,
162 inner: e.into(),
163 }
164 })?;
165
166 ArcRenderCommand::SetBindGroup {
167 index,
168 num_dynamic_offsets,
169 bind_group: Some(bg),
170 }
171 }
172
173 RenderCommand::SetPipeline(pipeline_id) => ArcRenderCommand::SetPipeline(
174 pipelines_guard.get(pipeline_id).get().map_err(|e| {
175 RenderPassError {
176 scope: PassErrorScope::SetPipelineRender,
177 inner: e.into(),
178 }
179 })?,
180 ),
181
182 RenderCommand::SetPushConstant {
183 offset,
184 size_bytes,
185 values_offset,
186 stages,
187 } => ArcRenderCommand::SetPushConstant {
188 offset,
189 size_bytes,
190 values_offset,
191 stages,
192 },
193
194 RenderCommand::PushDebugGroup { color, len } => {
195 ArcRenderCommand::PushDebugGroup { color, len }
196 }
197
198 RenderCommand::PopDebugGroup => ArcRenderCommand::PopDebugGroup,
199
200 RenderCommand::InsertDebugMarker { color, len } => {
201 ArcRenderCommand::InsertDebugMarker { color, len }
202 }
203
204 RenderCommand::WriteTimestamp {
205 query_set_id,
206 query_index,
207 } => ArcRenderCommand::WriteTimestamp {
208 query_set: query_set_guard.get(query_set_id).get().map_err(|e| {
209 RenderPassError {
210 scope: PassErrorScope::WriteTimestamp,
211 inner: e.into(),
212 }
213 })?,
214 query_index,
215 },
216
217 RenderCommand::BeginPipelineStatisticsQuery {
218 query_set_id,
219 query_index,
220 } => ArcRenderCommand::BeginPipelineStatisticsQuery {
221 query_set: query_set_guard.get(query_set_id).get().map_err(|e| {
222 RenderPassError {
223 scope: PassErrorScope::BeginPipelineStatisticsQuery,
224 inner: e.into(),
225 }
226 })?,
227 query_index,
228 },
229
230 RenderCommand::EndPipelineStatisticsQuery => {
231 ArcRenderCommand::EndPipelineStatisticsQuery
232 }
233
234 RenderCommand::SetIndexBuffer {
235 buffer_id,
236 index_format,
237 offset,
238 size,
239 } => ArcRenderCommand::SetIndexBuffer {
240 buffer: buffers_guard.get(buffer_id).get().map_err(|e| {
241 RenderPassError {
242 scope: PassErrorScope::SetIndexBuffer,
243 inner: e.into(),
244 }
245 })?,
246 index_format,
247 offset,
248 size,
249 },
250
251 RenderCommand::SetVertexBuffer {
252 slot,
253 buffer_id,
254 offset,
255 size,
256 } => ArcRenderCommand::SetVertexBuffer {
257 slot,
258 buffer: buffers_guard.get(buffer_id).get().map_err(|e| {
259 RenderPassError {
260 scope: PassErrorScope::SetVertexBuffer,
261 inner: e.into(),
262 }
263 })?,
264 offset,
265 size,
266 },
267
268 RenderCommand::SetBlendConstant(color) => {
269 ArcRenderCommand::SetBlendConstant(color)
270 }
271
272 RenderCommand::SetStencilReference(reference) => {
273 ArcRenderCommand::SetStencilReference(reference)
274 }
275
276 RenderCommand::SetViewport {
277 rect,
278 depth_min,
279 depth_max,
280 } => ArcRenderCommand::SetViewport {
281 rect,
282 depth_min,
283 depth_max,
284 },
285
286 RenderCommand::SetScissor(scissor) => ArcRenderCommand::SetScissor(scissor),
287
288 RenderCommand::Draw {
289 vertex_count,
290 instance_count,
291 first_vertex,
292 first_instance,
293 } => ArcRenderCommand::Draw {
294 vertex_count,
295 instance_count,
296 first_vertex,
297 first_instance,
298 },
299
300 RenderCommand::DrawIndexed {
301 index_count,
302 instance_count,
303 first_index,
304 base_vertex,
305 first_instance,
306 } => ArcRenderCommand::DrawIndexed {
307 index_count,
308 instance_count,
309 first_index,
310 base_vertex,
311 first_instance,
312 },
313
314 RenderCommand::DrawIndirect {
315 buffer_id,
316 offset,
317 count,
318 indexed,
319 } => ArcRenderCommand::DrawIndirect {
320 buffer: buffers_guard.get(buffer_id).get().map_err(|e| {
321 RenderPassError {
322 scope: PassErrorScope::Draw {
323 kind: if count != 1 {
324 DrawKind::MultiDrawIndirect
325 } else {
326 DrawKind::DrawIndirect
327 },
328 indexed,
329 },
330 inner: e.into(),
331 }
332 })?,
333 offset,
334 count,
335 indexed,
336
337 vertex_or_index_limit: 0,
338 instance_limit: 0,
339 },
340
341 RenderCommand::MultiDrawIndirectCount {
342 buffer_id,
343 offset,
344 count_buffer_id,
345 count_buffer_offset,
346 max_count,
347 indexed,
348 } => {
349 let scope = PassErrorScope::Draw {
350 kind: DrawKind::MultiDrawIndirectCount,
351 indexed,
352 };
353 ArcRenderCommand::MultiDrawIndirectCount {
354 buffer: buffers_guard.get(buffer_id).get().map_err(|e| {
355 RenderPassError {
356 scope,
357 inner: e.into(),
358 }
359 })?,
360 offset,
361 count_buffer: buffers_guard.get(count_buffer_id).get().map_err(
362 |e| RenderPassError {
363 scope,
364 inner: e.into(),
365 },
366 )?,
367 count_buffer_offset,
368 max_count,
369 indexed,
370 }
371 }
372
373 RenderCommand::BeginOcclusionQuery { query_index } => {
374 ArcRenderCommand::BeginOcclusionQuery { query_index }
375 }
376
377 RenderCommand::EndOcclusionQuery => ArcRenderCommand::EndOcclusionQuery,
378
379 RenderCommand::ExecuteBundle(bundle) => ArcRenderCommand::ExecuteBundle(
380 render_bundles_guard.get(bundle).get().map_err(|e| {
381 RenderPassError {
382 scope: PassErrorScope::ExecuteBundle,
383 inner: e.into(),
384 }
385 })?,
386 ),
387 })
388 })
389 .collect::<Result<Vec<_>, RenderPassError>>()?;
390 Ok(resolved_commands)
391 }
392}
393
394#[doc(hidden)]
396#[derive(Clone, Debug)]
397pub enum ArcRenderCommand {
398 SetBindGroup {
399 index: u32,
400 num_dynamic_offsets: usize,
401 bind_group: Option<Arc<BindGroup>>,
402 },
403 SetPipeline(Arc<RenderPipeline>),
404 SetIndexBuffer {
405 buffer: Arc<Buffer>,
406 index_format: wgt::IndexFormat,
407 offset: BufferAddress,
408 size: Option<BufferSize>,
409 },
410 SetVertexBuffer {
411 slot: u32,
412 buffer: Arc<Buffer>,
413 offset: BufferAddress,
414 size: Option<BufferSize>,
415 },
416 SetBlendConstant(Color),
417 SetStencilReference(u32),
418 SetViewport {
419 rect: Rect<f32>,
420 depth_min: f32,
421 depth_max: f32,
422 },
423 SetScissor(Rect<u32>),
424
425 SetPushConstant {
430 stages: wgt::ShaderStages,
432
433 offset: u32,
436
437 size_bytes: u32,
439
440 values_offset: Option<u32>,
451 },
452 Draw {
453 vertex_count: u32,
454 instance_count: u32,
455 first_vertex: u32,
456 first_instance: u32,
457 },
458 DrawIndexed {
459 index_count: u32,
460 instance_count: u32,
461 first_index: u32,
462 base_vertex: i32,
463 first_instance: u32,
464 },
465 DrawIndirect {
466 buffer: Arc<Buffer>,
467 offset: BufferAddress,
468 count: u32,
469 indexed: bool,
470
471 vertex_or_index_limit: u64,
473 instance_limit: u64,
475 },
476 MultiDrawIndirectCount {
477 buffer: Arc<Buffer>,
478 offset: BufferAddress,
479 count_buffer: Arc<Buffer>,
480 count_buffer_offset: BufferAddress,
481 max_count: u32,
482 indexed: bool,
483 },
484 PushDebugGroup {
485 #[cfg_attr(not(any(feature = "serde", feature = "replay")), allow(dead_code))]
486 color: u32,
487 len: usize,
488 },
489 PopDebugGroup,
490 InsertDebugMarker {
491 #[cfg_attr(not(any(feature = "serde", feature = "replay")), allow(dead_code))]
492 color: u32,
493 len: usize,
494 },
495 WriteTimestamp {
496 query_set: Arc<QuerySet>,
497 query_index: u32,
498 },
499 BeginOcclusionQuery {
500 query_index: u32,
501 },
502 EndOcclusionQuery,
503 BeginPipelineStatisticsQuery {
504 query_set: Arc<QuerySet>,
505 query_index: u32,
506 },
507 EndPipelineStatisticsQuery,
508 ExecuteBundle(Arc<RenderBundle>),
509}