rafx_api/
command_buffer.rs

1#[cfg(feature = "rafx-dx12")]
2use crate::dx12::RafxCommandBufferDx12;
3#[cfg(any(
4    feature = "rafx-empty",
5    not(any(
6        feature = "rafx-dx12",
7        feature = "rafx-metal",
8        feature = "rafx-vulkan",
9        feature = "rafx-gles2",
10        feature = "rafx-gles3"
11    ))
12))]
13use crate::empty::RafxCommandBufferEmpty;
14#[cfg(feature = "rafx-gles2")]
15use crate::gles2::RafxCommandBufferGles2;
16#[cfg(feature = "rafx-gles3")]
17use crate::gles3::RafxCommandBufferGles3;
18#[cfg(feature = "rafx-metal")]
19use crate::metal::RafxCommandBufferMetal;
20#[cfg(feature = "rafx-vulkan")]
21use crate::vulkan::RafxCommandBufferVulkan;
22use crate::{
23    RafxBuffer, RafxBufferBarrier, RafxCmdCopyBufferToBufferParams,
24    RafxCmdCopyBufferToTextureParams, RafxCmdCopyTextureToTextureParams,
25    RafxColorRenderTargetBinding, RafxDepthStencilRenderTargetBinding, RafxDescriptorIndex,
26    RafxDescriptorSetArray, RafxDescriptorSetHandle, RafxIndexBufferBinding, RafxPipeline,
27    RafxResult, RafxRootSignature, RafxTexture, RafxTextureBarrier, RafxVertexBufferBinding,
28};
29
30/// A list of commands recorded by the CPU and submitted to the GPU.
31///
32/// It cannot be created directly. It must be allocated out of a pool.
33///
34/// The command pool and all command buffers allocated from it share memory. The standard rust rules
35/// about mutability apply but are not enforced at compile time or runtime.
36///  * Do not modify two command buffers from the same pool concurrently
37///  * Do not allocate from a command pool while modifying one of its command buffers
38///  * Once a command buffer is submitted to the GPU, do not modify its pool, or any command buffers
39///    created from it, until the GPU completes its work.
40///
41/// In general, do not modify textures, buffers, command buffers, or other GPU resources while a
42/// command buffer referencing them is submitted. Additionally, these resources must persist for
43/// the entire duration of the submitted workload.
44///
45/// Semaphores and fences can be used for achieve the more fine-grained scheduling necessary to
46/// modify resources that are referenced from a submitted and in-use command buffer.
47///
48/// Command pools MAY be dropped if they are in use by the GPU, but the command pool must not be
49/// dropped. Dropped command pools that are not returned to the pool will not be available for
50/// reuse.
51#[derive(Debug)]
52pub enum RafxCommandBuffer {
53    #[cfg(feature = "rafx-dx12")]
54    Dx12(RafxCommandBufferDx12),
55
56    #[cfg(feature = "rafx-vulkan")]
57    Vk(RafxCommandBufferVulkan),
58
59    #[cfg(feature = "rafx-metal")]
60    Metal(RafxCommandBufferMetal),
61
62    #[cfg(feature = "rafx-gles2")]
63    Gles2(RafxCommandBufferGles2),
64
65    #[cfg(feature = "rafx-gles3")]
66    Gles3(RafxCommandBufferGles3),
67
68    #[cfg(any(
69        feature = "rafx-empty",
70        not(any(
71            feature = "rafx-dx12",
72            feature = "rafx-metal",
73            feature = "rafx-vulkan",
74            feature = "rafx-gles2",
75            feature = "rafx-gles3"
76        ))
77    ))]
78    Empty(RafxCommandBufferEmpty),
79}
80
81impl RafxCommandBuffer {
82    /// Begins writing a command buffer. This can only be called when the command buffer is first
83    /// allocated or if the pool has been reset since it was last written
84    pub fn begin(&self) -> RafxResult<()> {
85        match self {
86            #[cfg(feature = "rafx-dx12")]
87            RafxCommandBuffer::Dx12(inner) => inner.begin(),
88            #[cfg(feature = "rafx-vulkan")]
89            RafxCommandBuffer::Vk(inner) => inner.begin(),
90            #[cfg(feature = "rafx-metal")]
91            RafxCommandBuffer::Metal(inner) => inner.begin(),
92            #[cfg(feature = "rafx-gles2")]
93            RafxCommandBuffer::Gles2(inner) => inner.begin(),
94            #[cfg(feature = "rafx-gles3")]
95            RafxCommandBuffer::Gles3(inner) => inner.begin(),
96            #[cfg(any(
97                feature = "rafx-empty",
98                not(any(
99                    feature = "rafx-dx12",
100                    feature = "rafx-metal",
101                    feature = "rafx-vulkan",
102                    feature = "rafx-gles2",
103                    feature = "rafx-gles3"
104                ))
105            ))]
106            RafxCommandBuffer::Empty(inner) => inner.begin(),
107        }
108    }
109
110    /// End writing the command buffer. This must be called before submitting the command buffer
111    /// to the GPU
112    pub fn end(&self) -> RafxResult<()> {
113        match self {
114            #[cfg(feature = "rafx-dx12")]
115            RafxCommandBuffer::Dx12(inner) => inner.end(),
116            #[cfg(feature = "rafx-vulkan")]
117            RafxCommandBuffer::Vk(inner) => inner.end(),
118            #[cfg(feature = "rafx-metal")]
119            RafxCommandBuffer::Metal(inner) => inner.end(),
120            #[cfg(feature = "rafx-gles2")]
121            RafxCommandBuffer::Gles2(inner) => inner.end(),
122            #[cfg(feature = "rafx-gles3")]
123            RafxCommandBuffer::Gles3(inner) => inner.end(),
124            #[cfg(any(
125                feature = "rafx-empty",
126                not(any(
127                    feature = "rafx-dx12",
128                    feature = "rafx-metal",
129                    feature = "rafx-vulkan",
130                    feature = "rafx-gles2",
131                    feature = "rafx-gles3"
132                ))
133            ))]
134            RafxCommandBuffer::Empty(inner) => inner.end(),
135        }
136    }
137
138    /// This returns the command buffer to the pool, allowing it to be allocated again. This must
139    /// not be called if the command buffer is still in-use by the GPU.
140    ///
141    /// Dropping a command buffer without returning it to the pool is allowed. In this case, it
142    /// remains usable by the GPU until the command pool is dropped. However, even if the command
143    /// buffer is reset, this command buffer will not be available for use again.
144    pub fn return_to_pool(&self) -> RafxResult<()> {
145        match self {
146            #[cfg(feature = "rafx-dx12")]
147            RafxCommandBuffer::Dx12(inner) => inner.return_to_pool(),
148            #[cfg(feature = "rafx-vulkan")]
149            RafxCommandBuffer::Vk(inner) => inner.return_to_pool(),
150            #[cfg(feature = "rafx-metal")]
151            RafxCommandBuffer::Metal(inner) => inner.return_to_pool(),
152            #[cfg(feature = "rafx-gles2")]
153            RafxCommandBuffer::Gles2(inner) => inner.return_to_pool(),
154            #[cfg(feature = "rafx-gles3")]
155            RafxCommandBuffer::Gles3(inner) => inner.return_to_pool(),
156            #[cfg(any(
157                feature = "rafx-empty",
158                not(any(
159                    feature = "rafx-dx12",
160                    feature = "rafx-metal",
161                    feature = "rafx-vulkan",
162                    feature = "rafx-gles2",
163                    feature = "rafx-gles3"
164                ))
165            ))]
166            RafxCommandBuffer::Empty(inner) => inner.return_to_pool(),
167        }
168    }
169
170    /// Begin a new renderpass using the given color targets and depth targets. This is similar to
171    /// beginning a renderpass in vulkan.
172    ///
173    /// Some command must be used within a renderpass and some may only be used outside of a
174    /// renderpass.
175    pub fn cmd_begin_render_pass(
176        &self,
177        color_targets: &[RafxColorRenderTargetBinding],
178        depth_target: Option<RafxDepthStencilRenderTargetBinding>,
179    ) -> RafxResult<()> {
180        match self {
181            #[cfg(feature = "rafx-dx12")]
182            RafxCommandBuffer::Dx12(inner) => {
183                inner.cmd_begin_render_pass(color_targets, depth_target)
184            }
185            #[cfg(feature = "rafx-vulkan")]
186            RafxCommandBuffer::Vk(inner) => {
187                inner.cmd_begin_render_pass(color_targets, depth_target)
188            }
189            #[cfg(feature = "rafx-metal")]
190            RafxCommandBuffer::Metal(inner) => {
191                inner.cmd_begin_render_pass(color_targets, depth_target)
192            }
193            #[cfg(feature = "rafx-gles2")]
194            RafxCommandBuffer::Gles2(inner) => {
195                inner.cmd_begin_render_pass(color_targets, depth_target)
196            }
197            #[cfg(feature = "rafx-gles3")]
198            RafxCommandBuffer::Gles3(inner) => {
199                inner.cmd_begin_render_pass(color_targets, depth_target)
200            }
201            #[cfg(any(
202                feature = "rafx-empty",
203                not(any(
204                    feature = "rafx-dx12",
205                    feature = "rafx-metal",
206                    feature = "rafx-vulkan",
207                    feature = "rafx-gles2",
208                    feature = "rafx-gles3"
209                ))
210            ))]
211            RafxCommandBuffer::Empty(inner) => {
212                inner.cmd_begin_render_pass(color_targets, depth_target)
213            }
214        }
215    }
216
217    /// Finish the renderpass.
218    pub fn cmd_end_render_pass(&self) -> RafxResult<()> {
219        match self {
220            #[cfg(feature = "rafx-dx12")]
221            RafxCommandBuffer::Dx12(inner) => inner.cmd_end_render_pass(),
222            #[cfg(feature = "rafx-vulkan")]
223            RafxCommandBuffer::Vk(inner) => inner.cmd_end_render_pass(),
224            #[cfg(feature = "rafx-metal")]
225            RafxCommandBuffer::Metal(inner) => inner.cmd_end_render_pass(),
226            #[cfg(feature = "rafx-gles2")]
227            RafxCommandBuffer::Gles2(inner) => inner.cmd_end_render_pass(),
228            #[cfg(feature = "rafx-gles3")]
229            RafxCommandBuffer::Gles3(inner) => inner.cmd_end_render_pass(),
230            #[cfg(any(
231                feature = "rafx-empty",
232                not(any(
233                    feature = "rafx-dx12",
234                    feature = "rafx-metal",
235                    feature = "rafx-vulkan",
236                    feature = "rafx-gles2",
237                    feature = "rafx-gles3"
238                ))
239            ))]
240            RafxCommandBuffer::Empty(inner) => inner.cmd_end_render_pass(),
241        }
242    }
243
244    /// Set the viewport state. This may be called inside or outside of a renderpass.
245    ///
246    /// Viewport state defines where on the screen the draw will occur.
247    pub fn cmd_set_viewport(
248        &self,
249        x: f32,
250        y: f32,
251        width: f32,
252        height: f32,
253        depth_min: f32,
254        depth_max: f32,
255    ) -> RafxResult<()> {
256        match self {
257            #[cfg(feature = "rafx-dx12")]
258            RafxCommandBuffer::Dx12(inner) => {
259                inner.cmd_set_viewport(x, y, width, height, depth_min, depth_max)
260            }
261            #[cfg(feature = "rafx-vulkan")]
262            RafxCommandBuffer::Vk(inner) => {
263                inner.cmd_set_viewport(x, y, width, height, depth_min, depth_max)
264            }
265            #[cfg(feature = "rafx-metal")]
266            RafxCommandBuffer::Metal(inner) => {
267                inner.cmd_set_viewport(x, y, width, height, depth_min, depth_max)
268            }
269            #[cfg(feature = "rafx-gles2")]
270            RafxCommandBuffer::Gles2(inner) => {
271                inner.cmd_set_viewport(x, y, width, height, depth_min, depth_max)
272            }
273            #[cfg(feature = "rafx-gles3")]
274            RafxCommandBuffer::Gles3(inner) => {
275                inner.cmd_set_viewport(x, y, width, height, depth_min, depth_max)
276            }
277            #[cfg(any(
278                feature = "rafx-empty",
279                not(any(
280                    feature = "rafx-dx12",
281                    feature = "rafx-metal",
282                    feature = "rafx-vulkan",
283                    feature = "rafx-gles2",
284                    feature = "rafx-gles3"
285                ))
286            ))]
287            RafxCommandBuffer::Empty(inner) => {
288                inner.cmd_set_viewport(x, y, width, height, depth_min, depth_max)
289            }
290        }
291    }
292
293    /// Set the scissor state. This may be called inside or outside of a renderpass.
294    ///
295    /// Scissor state can be used to restrict rendering to a specific area of a render target
296    pub fn cmd_set_scissor(
297        &self,
298        x: u32,
299        y: u32,
300        width: u32,
301        height: u32,
302    ) -> RafxResult<()> {
303        match self {
304            #[cfg(feature = "rafx-dx12")]
305            RafxCommandBuffer::Dx12(inner) => inner.cmd_set_scissor(x, y, width, height),
306            #[cfg(feature = "rafx-vulkan")]
307            RafxCommandBuffer::Vk(inner) => inner.cmd_set_scissor(x, y, width, height),
308            #[cfg(feature = "rafx-metal")]
309            RafxCommandBuffer::Metal(inner) => inner.cmd_set_scissor(x, y, width, height),
310            #[cfg(feature = "rafx-gles2")]
311            RafxCommandBuffer::Gles2(inner) => inner.cmd_set_scissor(x, y, width, height),
312            #[cfg(feature = "rafx-gles3")]
313            RafxCommandBuffer::Gles3(inner) => inner.cmd_set_scissor(x, y, width, height),
314            #[cfg(any(
315                feature = "rafx-empty",
316                not(any(
317                    feature = "rafx-dx12",
318                    feature = "rafx-metal",
319                    feature = "rafx-vulkan",
320                    feature = "rafx-gles2",
321                    feature = "rafx-gles3"
322                ))
323            ))]
324            RafxCommandBuffer::Empty(inner) => inner.cmd_set_scissor(x, y, width, height),
325        }
326    }
327
328    /// Set the stencil buffer state. This may be called inside or outside of a renderpass.
329    ///
330    /// Stencil buffer state is used with a stencil render target to discard rendering results in
331    /// specific portions of a render target
332    pub fn cmd_set_stencil_reference_value(
333        &self,
334        value: u32,
335    ) -> RafxResult<()> {
336        match self {
337            #[cfg(feature = "rafx-dx12")]
338            RafxCommandBuffer::Dx12(inner) => inner.cmd_set_stencil_reference_value(value),
339            #[cfg(feature = "rafx-vulkan")]
340            RafxCommandBuffer::Vk(inner) => inner.cmd_set_stencil_reference_value(value),
341            #[cfg(feature = "rafx-metal")]
342            RafxCommandBuffer::Metal(inner) => inner.cmd_set_stencil_reference_value(value),
343            #[cfg(feature = "rafx-gles2")]
344            RafxCommandBuffer::Gles2(inner) => inner.cmd_set_stencil_reference_value(value),
345            #[cfg(feature = "rafx-gles3")]
346            RafxCommandBuffer::Gles3(inner) => inner.cmd_set_stencil_reference_value(value),
347            #[cfg(any(
348                feature = "rafx-empty",
349                not(any(
350                    feature = "rafx-dx12",
351                    feature = "rafx-metal",
352                    feature = "rafx-vulkan",
353                    feature = "rafx-gles2",
354                    feature = "rafx-gles3"
355                ))
356            ))]
357            RafxCommandBuffer::Empty(inner) => inner.cmd_set_stencil_reference_value(value),
358        }
359    }
360
361    /// Binds the given pipeline - which represents fixed-function state and shaders. Draw calls
362    /// that produce primitives or dispatch compute will use the bound pipeline.
363    pub fn cmd_bind_pipeline(
364        &self,
365        pipeline: &RafxPipeline,
366    ) -> RafxResult<()> {
367        match self {
368            #[cfg(feature = "rafx-dx12")]
369            RafxCommandBuffer::Dx12(inner) => {
370                inner.cmd_bind_pipeline(pipeline.dx12_pipeline().unwrap())
371            }
372            #[cfg(feature = "rafx-vulkan")]
373            RafxCommandBuffer::Vk(inner) => {
374                inner.cmd_bind_pipeline(pipeline.vk_pipeline().unwrap())
375            }
376            #[cfg(feature = "rafx-metal")]
377            RafxCommandBuffer::Metal(inner) => {
378                inner.cmd_bind_pipeline(pipeline.metal_pipeline().unwrap())
379            }
380            #[cfg(feature = "rafx-gles2")]
381            RafxCommandBuffer::Gles2(inner) => {
382                inner.cmd_bind_pipeline(pipeline.gles2_pipeline().unwrap())
383            }
384            #[cfg(feature = "rafx-gles3")]
385            RafxCommandBuffer::Gles3(inner) => {
386                inner.cmd_bind_pipeline(pipeline.gles3_pipeline().unwrap())
387            }
388            #[cfg(any(
389                feature = "rafx-empty",
390                not(any(
391                    feature = "rafx-dx12",
392                    feature = "rafx-metal",
393                    feature = "rafx-vulkan",
394                    feature = "rafx-gles2",
395                    feature = "rafx-gles3"
396                ))
397            ))]
398            RafxCommandBuffer::Empty(inner) => {
399                inner.cmd_bind_pipeline(pipeline.empty_pipeline().unwrap())
400            }
401        }
402    }
403
404    /// Binds a buffer as a vertex buffer. Draw calls will use this buffer as input.
405    ///
406    /// Multiple buffers can be bound, but the number is limited depending on API/hardware. Less
407    /// than 4 is a relatively safe number.
408    pub fn cmd_bind_vertex_buffers(
409        &self,
410        first_binding: u32,
411        bindings: &[RafxVertexBufferBinding],
412    ) -> RafxResult<()> {
413        match self {
414            #[cfg(feature = "rafx-dx12")]
415            RafxCommandBuffer::Dx12(inner) => {
416                inner.cmd_bind_vertex_buffers(first_binding, bindings)
417            }
418            #[cfg(feature = "rafx-vulkan")]
419            RafxCommandBuffer::Vk(inner) => inner.cmd_bind_vertex_buffers(first_binding, bindings),
420            #[cfg(feature = "rafx-metal")]
421            RafxCommandBuffer::Metal(inner) => {
422                inner.cmd_bind_vertex_buffers(first_binding, bindings)
423            }
424            #[cfg(feature = "rafx-gles2")]
425            RafxCommandBuffer::Gles2(inner) => {
426                inner.cmd_bind_vertex_buffers(first_binding, bindings)
427            }
428            #[cfg(feature = "rafx-gles3")]
429            RafxCommandBuffer::Gles3(inner) => {
430                inner.cmd_bind_vertex_buffers(first_binding, bindings)
431            }
432            #[cfg(any(
433                feature = "rafx-empty",
434                not(any(
435                    feature = "rafx-dx12",
436                    feature = "rafx-metal",
437                    feature = "rafx-vulkan",
438                    feature = "rafx-gles2",
439                    feature = "rafx-gles3"
440                ))
441            ))]
442            RafxCommandBuffer::Empty(inner) => {
443                inner.cmd_bind_vertex_buffers(first_binding, bindings)
444            }
445        }
446    }
447
448    /// Binds a buffer as a vertex buffer. Draw calls will use this buffer as input.
449    ///
450    /// Multiple buffers can be bound, but the number is limited depending on API/hardware. Less
451    /// than 4 is a relatively safe number.
452    pub fn cmd_bind_index_buffer(
453        &self,
454        binding: &RafxIndexBufferBinding,
455    ) -> RafxResult<()> {
456        match self {
457            #[cfg(feature = "rafx-dx12")]
458            RafxCommandBuffer::Dx12(inner) => inner.cmd_bind_index_buffer(binding),
459            #[cfg(feature = "rafx-vulkan")]
460            RafxCommandBuffer::Vk(inner) => inner.cmd_bind_index_buffer(binding),
461            #[cfg(feature = "rafx-metal")]
462            RafxCommandBuffer::Metal(inner) => inner.cmd_bind_index_buffer(binding),
463            #[cfg(feature = "rafx-gles2")]
464            RafxCommandBuffer::Gles2(inner) => inner.cmd_bind_index_buffer(binding),
465            #[cfg(feature = "rafx-gles3")]
466            RafxCommandBuffer::Gles3(inner) => inner.cmd_bind_index_buffer(binding),
467            #[cfg(any(
468                feature = "rafx-empty",
469                not(any(
470                    feature = "rafx-dx12",
471                    feature = "rafx-metal",
472                    feature = "rafx-vulkan",
473                    feature = "rafx-gles2",
474                    feature = "rafx-gles3"
475                ))
476            ))]
477            RafxCommandBuffer::Empty(inner) => inner.cmd_bind_index_buffer(binding),
478        }
479    }
480
481    /// Binds a descriptor set for use by the shader in the currently bound pipeline.
482    ///
483    /// Multiple descriptor sets can be bound, but the number is limited to 4.
484    pub fn cmd_bind_descriptor_set(
485        &self,
486        descriptor_set_array: &RafxDescriptorSetArray,
487        index: u32,
488    ) -> RafxResult<()> {
489        match self {
490            #[cfg(feature = "rafx-dx12")]
491            RafxCommandBuffer::Dx12(inner) => inner.cmd_bind_descriptor_set(
492                descriptor_set_array.dx12_descriptor_set_array().unwrap(),
493                index,
494            ),
495            #[cfg(feature = "rafx-vulkan")]
496            RafxCommandBuffer::Vk(inner) => inner.cmd_bind_descriptor_set(
497                descriptor_set_array.vk_descriptor_set_array().unwrap(),
498                index,
499            ),
500            #[cfg(feature = "rafx-metal")]
501            RafxCommandBuffer::Metal(inner) => inner.cmd_bind_descriptor_set(
502                descriptor_set_array.metal_descriptor_set_array().unwrap(),
503                index,
504            ),
505            #[cfg(feature = "rafx-gles2")]
506            RafxCommandBuffer::Gles2(inner) => inner.cmd_bind_descriptor_set(
507                descriptor_set_array.gles2_descriptor_set_array().unwrap(),
508                index,
509            ),
510            #[cfg(feature = "rafx-gles3")]
511            RafxCommandBuffer::Gles3(inner) => inner.cmd_bind_descriptor_set(
512                descriptor_set_array.gles3_descriptor_set_array().unwrap(),
513                index,
514            ),
515            #[cfg(any(
516                feature = "rafx-empty",
517                not(any(
518                    feature = "rafx-dx12",
519                    feature = "rafx-metal",
520                    feature = "rafx-vulkan",
521                    feature = "rafx-gles2",
522                    feature = "rafx-gles3"
523                ))
524            ))]
525            RafxCommandBuffer::Empty(inner) => inner.cmd_bind_descriptor_set(
526                descriptor_set_array.empty_descriptor_set_array().unwrap(),
527                index,
528            ),
529        }
530    }
531
532    /// Binds a descriptor set for use by the shader in the currently bound pipeline.
533    ///
534    /// This is the same as `cmd_bind_descriptor_set` but uses a lightweight, opaque handle. This
535    /// may make using the API easier in multi-threaded scenarios.
536    pub fn cmd_bind_descriptor_set_handle(
537        &self,
538        root_signature: &RafxRootSignature,
539        set_index: u32,
540        descriptor_set_handle: &RafxDescriptorSetHandle,
541    ) -> RafxResult<()> {
542        match self {
543            #[cfg(feature = "rafx-dx12")]
544            RafxCommandBuffer::Dx12(inner) => inner.cmd_bind_descriptor_set_handle(
545                root_signature.dx12_root_signature().unwrap(),
546                set_index,
547                descriptor_set_handle.dx12_descriptor_set_handle().unwrap(),
548            ),
549            #[cfg(feature = "rafx-vulkan")]
550            RafxCommandBuffer::Vk(inner) => inner.cmd_bind_descriptor_set_handle(
551                root_signature.vk_root_signature().unwrap(),
552                set_index,
553                descriptor_set_handle.vk_descriptor_set_handle().unwrap(),
554            ),
555            #[cfg(feature = "rafx-metal")]
556            RafxCommandBuffer::Metal(inner) => inner.cmd_bind_descriptor_set_handle(
557                root_signature.metal_root_signature().unwrap(),
558                set_index,
559                descriptor_set_handle.metal_descriptor_set_handle().unwrap(),
560            ),
561            #[cfg(feature = "rafx-gles2")]
562            RafxCommandBuffer::Gles2(inner) => inner.cmd_bind_descriptor_set_handle(
563                root_signature.gles2_root_signature().unwrap(),
564                set_index,
565                descriptor_set_handle.gles2_descriptor_set_handle().unwrap(),
566            ),
567            #[cfg(feature = "rafx-gles3")]
568            RafxCommandBuffer::Gles3(inner) => inner.cmd_bind_descriptor_set_handle(
569                root_signature.gles3_root_signature().unwrap(),
570                set_index,
571                descriptor_set_handle.gles3_descriptor_set_handle().unwrap(),
572            ),
573            #[cfg(any(
574                feature = "rafx-empty",
575                not(any(
576                    feature = "rafx-dx12",
577                    feature = "rafx-metal",
578                    feature = "rafx-vulkan",
579                    feature = "rafx-gles2",
580                    feature = "rafx-gles3"
581                ))
582            ))]
583            RafxCommandBuffer::Empty(inner) => inner.cmd_bind_descriptor_set_handle(
584                root_signature.empty_root_signature().unwrap(),
585                set_index,
586                descriptor_set_handle.empty_descriptor_set_handle().unwrap(),
587            ),
588        }
589    }
590
591    /// Binds a push constants for use by the shader in the currently bound pipeline.
592    ///
593    /// Multiple descriptor sets can be bound, but the number is limited to 4.
594    pub fn cmd_bind_push_constant<T: Copy>(
595        &self,
596        root_signature: &RafxRootSignature,
597        descriptor_index: RafxDescriptorIndex,
598        data: &T,
599    ) -> RafxResult<()> {
600        match self {
601            #[cfg(feature = "rafx-dx12")]
602            RafxCommandBuffer::Dx12(inner) => inner.cmd_bind_push_constant(
603                root_signature.dx12_root_signature().unwrap(),
604                descriptor_index,
605                data,
606            ),
607            #[cfg(feature = "rafx-vulkan")]
608            RafxCommandBuffer::Vk(inner) => inner.cmd_bind_push_constant(
609                root_signature.vk_root_signature().unwrap(),
610                descriptor_index,
611                data,
612            ),
613            #[cfg(feature = "rafx-metal")]
614            RafxCommandBuffer::Metal(inner) => inner.cmd_bind_push_constant(
615                root_signature.metal_root_signature().unwrap(),
616                descriptor_index,
617                data,
618            ),
619            #[cfg(feature = "rafx-gles2")]
620            RafxCommandBuffer::Gles2(_inner) => {
621                let _ = root_signature;
622                let _ = descriptor_index;
623                let _ = data;
624                unimplemented!()
625            }
626            #[cfg(feature = "rafx-gles3")]
627            RafxCommandBuffer::Gles3(_inner) => {
628                let _ = root_signature;
629                let _ = descriptor_index;
630                let _ = data;
631                unimplemented!()
632            }
633            #[cfg(any(
634                feature = "rafx-empty",
635                not(any(
636                    feature = "rafx-dx12",
637                    feature = "rafx-metal",
638                    feature = "rafx-vulkan",
639                    feature = "rafx-gles2",
640                    feature = "rafx-gles3"
641                ))
642            ))]
643            RafxCommandBuffer::Empty(inner) => inner.cmd_bind_push_constant(
644                root_signature.empty_root_signature().unwrap(),
645                descriptor_index,
646                data,
647            ),
648        }
649    }
650
651    /// Draw primitives using the currently bound pipeline and vertex buffer
652    pub fn cmd_draw(
653        &self,
654        vertex_count: u32,
655        first_vertex: u32,
656    ) -> RafxResult<()> {
657        match self {
658            #[cfg(feature = "rafx-dx12")]
659            RafxCommandBuffer::Dx12(inner) => inner.cmd_draw(vertex_count, first_vertex),
660            #[cfg(feature = "rafx-vulkan")]
661            RafxCommandBuffer::Vk(inner) => inner.cmd_draw(vertex_count, first_vertex),
662            #[cfg(feature = "rafx-metal")]
663            RafxCommandBuffer::Metal(inner) => inner.cmd_draw(vertex_count, first_vertex),
664            #[cfg(feature = "rafx-gles2")]
665            RafxCommandBuffer::Gles2(inner) => inner.cmd_draw(vertex_count, first_vertex),
666            #[cfg(feature = "rafx-gles3")]
667            RafxCommandBuffer::Gles3(inner) => inner.cmd_draw(vertex_count, first_vertex),
668            #[cfg(any(
669                feature = "rafx-empty",
670                not(any(
671                    feature = "rafx-dx12",
672                    feature = "rafx-metal",
673                    feature = "rafx-vulkan",
674                    feature = "rafx-gles2",
675                    feature = "rafx-gles3"
676                ))
677            ))]
678            RafxCommandBuffer::Empty(inner) => inner.cmd_draw(vertex_count, first_vertex),
679        }
680    }
681
682    /// Draw instanced primitives using the currently bound pipeline and vertex buffer
683    pub fn cmd_draw_instanced(
684        &self,
685        vertex_count: u32,
686        first_vertex: u32,
687        instance_count: u32,
688        first_instance: u32,
689    ) -> RafxResult<()> {
690        match self {
691            #[cfg(feature = "rafx-dx12")]
692            RafxCommandBuffer::Dx12(inner) => {
693                inner.cmd_draw_instanced(vertex_count, first_vertex, instance_count, first_instance)
694            }
695            #[cfg(feature = "rafx-vulkan")]
696            RafxCommandBuffer::Vk(inner) => {
697                inner.cmd_draw_instanced(vertex_count, first_vertex, instance_count, first_instance)
698            }
699            #[cfg(feature = "rafx-metal")]
700            RafxCommandBuffer::Metal(inner) => {
701                inner.cmd_draw_instanced(vertex_count, first_vertex, instance_count, first_instance)
702            }
703            #[cfg(feature = "rafx-gles2")]
704            RafxCommandBuffer::Gles2(inner) => {
705                inner.cmd_draw_instanced(vertex_count, first_vertex, instance_count, first_instance)
706            }
707            #[cfg(feature = "rafx-gles3")]
708            RafxCommandBuffer::Gles3(inner) => {
709                inner.cmd_draw_instanced(vertex_count, first_vertex, instance_count, first_instance)
710            }
711            #[cfg(any(
712                feature = "rafx-empty",
713                not(any(
714                    feature = "rafx-dx12",
715                    feature = "rafx-metal",
716                    feature = "rafx-vulkan",
717                    feature = "rafx-gles2",
718                    feature = "rafx-gles3"
719                ))
720            ))]
721            RafxCommandBuffer::Empty(inner) => {
722                inner.cmd_draw_instanced(vertex_count, first_vertex, instance_count, first_instance)
723            }
724        }
725    }
726
727    /// Draw primitives using the currently bound pipeline, vertex, and index buffer
728    /// index_count: Number of vertices to draw
729    /// first_index: Base index within the index buffer
730    /// vertex_offset: Value added to the vertex index before indexing into the vertex buffer
731    pub fn cmd_draw_indexed(
732        &self,
733        index_count: u32,
734        first_index: u32,
735        vertex_offset: i32,
736    ) -> RafxResult<()> {
737        match self {
738            #[cfg(feature = "rafx-dx12")]
739            RafxCommandBuffer::Dx12(inner) => {
740                inner.cmd_draw_indexed(index_count, first_index, vertex_offset)
741            }
742            #[cfg(feature = "rafx-vulkan")]
743            RafxCommandBuffer::Vk(inner) => {
744                inner.cmd_draw_indexed(index_count, first_index, vertex_offset)
745            }
746            #[cfg(feature = "rafx-metal")]
747            RafxCommandBuffer::Metal(inner) => {
748                inner.cmd_draw_indexed(index_count, first_index, vertex_offset)
749            }
750            #[cfg(feature = "rafx-gles2")]
751            RafxCommandBuffer::Gles2(inner) => {
752                inner.cmd_draw_indexed(index_count, first_index, vertex_offset)
753            }
754            #[cfg(feature = "rafx-gles3")]
755            RafxCommandBuffer::Gles3(inner) => {
756                inner.cmd_draw_indexed(index_count, first_index, vertex_offset)
757            }
758            #[cfg(any(
759                feature = "rafx-empty",
760                not(any(
761                    feature = "rafx-dx12",
762                    feature = "rafx-metal",
763                    feature = "rafx-vulkan",
764                    feature = "rafx-gles2",
765                    feature = "rafx-gles3"
766                ))
767            ))]
768            RafxCommandBuffer::Empty(inner) => {
769                inner.cmd_draw_indexed(index_count, first_index, vertex_offset)
770            }
771        }
772    }
773
774    /// Draw instanced primitives using the currently bound pipeline, vertex, and index buffer
775    pub fn cmd_draw_indexed_instanced(
776        &self,
777        index_count: u32,
778        first_index: u32,
779        instance_count: u32,
780        first_instance: u32,
781        vertex_offset: i32, // value added to the vertex index before indexing into the vertex buffer
782    ) -> RafxResult<()> {
783        match self {
784            #[cfg(feature = "rafx-dx12")]
785            RafxCommandBuffer::Dx12(inner) => inner.cmd_draw_indexed_instanced(
786                index_count,
787                first_index,
788                instance_count,
789                first_instance,
790                vertex_offset,
791            ),
792            #[cfg(feature = "rafx-vulkan")]
793            RafxCommandBuffer::Vk(inner) => inner.cmd_draw_indexed_instanced(
794                index_count,
795                first_index,
796                instance_count,
797                first_instance,
798                vertex_offset,
799            ),
800            #[cfg(feature = "rafx-metal")]
801            RafxCommandBuffer::Metal(inner) => inner.cmd_draw_indexed_instanced(
802                index_count,
803                first_index,
804                instance_count,
805                first_instance,
806                vertex_offset,
807            ),
808            #[cfg(feature = "rafx-gles2")]
809            RafxCommandBuffer::Gles2(inner) => inner.cmd_draw_indexed_instanced(
810                index_count,
811                first_index,
812                instance_count,
813                first_instance,
814                vertex_offset,
815            ),
816            #[cfg(feature = "rafx-gles3")]
817            RafxCommandBuffer::Gles3(inner) => inner.cmd_draw_indexed_instanced(
818                index_count,
819                first_index,
820                instance_count,
821                first_instance,
822                vertex_offset,
823            ),
824            #[cfg(any(
825                feature = "rafx-empty",
826                not(any(
827                    feature = "rafx-dx12",
828                    feature = "rafx-metal",
829                    feature = "rafx-vulkan",
830                    feature = "rafx-gles2",
831                    feature = "rafx-gles3"
832                ))
833            ))]
834            RafxCommandBuffer::Empty(inner) => inner.cmd_draw_indexed_instanced(
835                index_count,
836                first_index,
837                instance_count,
838                first_instance,
839                vertex_offset,
840            ),
841        }
842    }
843
844    pub fn cmd_draw_indirect(
845        &self,
846        indirect_buffer: &RafxBuffer,
847        indirect_buffer_offset_in_bytes: u32,
848        draw_count: u32,
849    ) -> RafxResult<()> {
850        match self {
851            #[cfg(feature = "rafx-dx12")]
852            RafxCommandBuffer::Dx12(inner) => inner.cmd_draw_indirect(
853                indirect_buffer.dx12_buffer().unwrap(),
854                indirect_buffer_offset_in_bytes,
855                draw_count,
856            ),
857            #[cfg(feature = "rafx-vulkan")]
858            RafxCommandBuffer::Vk(inner) => inner.cmd_draw_indirect(
859                indirect_buffer.vk_buffer().unwrap(),
860                indirect_buffer_offset_in_bytes,
861                draw_count,
862            ),
863            #[cfg(feature = "rafx-metal")]
864            RafxCommandBuffer::Metal(inner) => inner.cmd_draw_indirect(
865                indirect_buffer.metal_buffer().unwrap(),
866                indirect_buffer_offset_in_bytes,
867                draw_count,
868            ),
869            #[cfg(feature = "rafx-gles2")]
870            RafxCommandBuffer::Gles2(_) => {
871                let _ = indirect_buffer;
872                let _ = indirect_buffer_offset_in_bytes;
873                let _ = draw_count;
874                unimplemented!()
875            }
876            #[cfg(feature = "rafx-gles3")]
877            RafxCommandBuffer::Gles3(_) => {
878                let _ = indirect_buffer;
879                let _ = indirect_buffer_offset_in_bytes;
880                let _ = draw_count;
881                unimplemented!()
882            }
883            #[cfg(any(
884                feature = "rafx-empty",
885                not(any(
886                    feature = "rafx-dx12",
887                    feature = "rafx-metal",
888                    feature = "rafx-vulkan",
889                    feature = "rafx-gles2",
890                    feature = "rafx-gles3"
891                ))
892            ))]
893            RafxCommandBuffer::Empty(inner) => inner.cmd_draw_indirect(
894                indirect_buffer.empty_buffer().unwrap(),
895                indirect_buffer_offset_in_bytes,
896                draw_count,
897            ),
898        }
899    }
900
901    pub fn cmd_draw_indexed_indirect(
902        &self,
903        indirect_buffer: &RafxBuffer,
904        indirect_buffer_offset_in_bytes: u32,
905        draw_count: u32,
906    ) -> RafxResult<()> {
907        match self {
908            #[cfg(feature = "rafx-dx12")]
909            RafxCommandBuffer::Dx12(inner) => inner.cmd_draw_indexed_indirect(
910                indirect_buffer.dx12_buffer().unwrap(),
911                indirect_buffer_offset_in_bytes,
912                draw_count,
913            ),
914            #[cfg(feature = "rafx-vulkan")]
915            RafxCommandBuffer::Vk(inner) => inner.cmd_draw_indexed_indirect(
916                indirect_buffer.vk_buffer().unwrap(),
917                indirect_buffer_offset_in_bytes,
918                draw_count,
919            ),
920            #[cfg(feature = "rafx-metal")]
921            RafxCommandBuffer::Metal(inner) => inner.cmd_draw_indexed_indirect(
922                indirect_buffer.metal_buffer().unwrap(),
923                indirect_buffer_offset_in_bytes,
924                draw_count,
925            ),
926            #[cfg(feature = "rafx-gles2")]
927            RafxCommandBuffer::Gles2(_) => {
928                let _ = indirect_buffer;
929                let _ = indirect_buffer_offset_in_bytes;
930                let _ = draw_count;
931                unimplemented!()
932            }
933            #[cfg(feature = "rafx-gles3")]
934            RafxCommandBuffer::Gles3(_) => {
935                let _ = indirect_buffer;
936                let _ = indirect_buffer_offset_in_bytes;
937                let _ = draw_count;
938                unimplemented!()
939            }
940            #[cfg(any(
941                feature = "rafx-empty",
942                not(any(
943                    feature = "rafx-dx12",
944                    feature = "rafx-metal",
945                    feature = "rafx-vulkan",
946                    feature = "rafx-gles2",
947                    feature = "rafx-gles3"
948                ))
949            ))]
950            RafxCommandBuffer::Empty(inner) => inner.cmd_draw_indexed_indirect(
951                indirect_buffer.empty_buffer().unwrap(),
952                indirect_buffer_offset_in_bytes,
953                draw_count,
954            ),
955        }
956    }
957
958    /// Dispatch the current pipeline. Only usable with compute pipelines.
959    pub fn cmd_dispatch(
960        &self,
961        group_count_x: u32,
962        group_count_y: u32,
963        group_count_z: u32,
964    ) -> RafxResult<()> {
965        match self {
966            #[cfg(feature = "rafx-dx12")]
967            RafxCommandBuffer::Dx12(inner) => {
968                inner.cmd_dispatch(group_count_x, group_count_y, group_count_z)
969            }
970            #[cfg(feature = "rafx-vulkan")]
971            RafxCommandBuffer::Vk(inner) => {
972                inner.cmd_dispatch(group_count_x, group_count_y, group_count_z)
973            }
974            #[cfg(feature = "rafx-metal")]
975            RafxCommandBuffer::Metal(inner) => {
976                inner.cmd_dispatch(group_count_x, group_count_y, group_count_z)
977            }
978            #[cfg(feature = "rafx-gles2")]
979            RafxCommandBuffer::Gles2(inner) => {
980                inner.cmd_dispatch(group_count_x, group_count_y, group_count_z)
981            }
982            #[cfg(feature = "rafx-gles3")]
983            RafxCommandBuffer::Gles3(inner) => {
984                inner.cmd_dispatch(group_count_x, group_count_y, group_count_z)
985            }
986            #[cfg(any(
987                feature = "rafx-empty",
988                not(any(
989                    feature = "rafx-dx12",
990                    feature = "rafx-metal",
991                    feature = "rafx-vulkan",
992                    feature = "rafx-gles2",
993                    feature = "rafx-gles3"
994                ))
995            ))]
996            RafxCommandBuffer::Empty(inner) => {
997                inner.cmd_dispatch(group_count_x, group_count_y, group_count_z)
998            }
999        }
1000    }
1001
1002    /// Add a memory barrier for one or more resources. This must occur OUTSIDE of a renderpass.
1003    pub fn cmd_resource_barrier(
1004        &self,
1005        buffer_barriers: &[RafxBufferBarrier],
1006        texture_barriers: &[RafxTextureBarrier],
1007    ) -> RafxResult<()> {
1008        match self {
1009            #[cfg(feature = "rafx-dx12")]
1010            RafxCommandBuffer::Dx12(inner) => {
1011                inner.cmd_resource_barrier(buffer_barriers, texture_barriers)
1012            }
1013            #[cfg(feature = "rafx-vulkan")]
1014            RafxCommandBuffer::Vk(inner) => {
1015                inner.cmd_resource_barrier(buffer_barriers, texture_barriers)
1016            }
1017            #[cfg(feature = "rafx-metal")]
1018            RafxCommandBuffer::Metal(inner) => {
1019                inner.cmd_resource_barrier(buffer_barriers, texture_barriers)
1020            }
1021            #[cfg(feature = "rafx-gles2")]
1022            RafxCommandBuffer::Gles2(inner) => {
1023                inner.cmd_resource_barrier(buffer_barriers, texture_barriers)
1024            }
1025            #[cfg(feature = "rafx-gles3")]
1026            RafxCommandBuffer::Gles3(inner) => {
1027                inner.cmd_resource_barrier(buffer_barriers, texture_barriers)
1028            }
1029            #[cfg(any(
1030                feature = "rafx-empty",
1031                not(any(
1032                    feature = "rafx-dx12",
1033                    feature = "rafx-metal",
1034                    feature = "rafx-vulkan",
1035                    feature = "rafx-gles2",
1036                    feature = "rafx-gles3"
1037                ))
1038            ))]
1039            RafxCommandBuffer::Empty(inner) => {
1040                inner.cmd_resource_barrier(buffer_barriers, texture_barriers)
1041            }
1042        }
1043    }
1044
1045    /// Copy the contents of one buffer into another. This occurs on the GPU and allows modifying
1046    /// resources that are not accessible to the CPU.
1047    pub fn cmd_copy_buffer_to_buffer(
1048        &self,
1049        src_buffer: &RafxBuffer,
1050        dst_buffer: &RafxBuffer,
1051        params: &RafxCmdCopyBufferToBufferParams,
1052    ) -> RafxResult<()> {
1053        match self {
1054            #[cfg(feature = "rafx-dx12")]
1055            RafxCommandBuffer::Dx12(inner) => inner.cmd_copy_buffer_to_buffer(
1056                src_buffer.dx12_buffer().unwrap(),
1057                dst_buffer.dx12_buffer().unwrap(),
1058                params,
1059            ),
1060            #[cfg(feature = "rafx-vulkan")]
1061            RafxCommandBuffer::Vk(inner) => inner.cmd_copy_buffer_to_buffer(
1062                src_buffer.vk_buffer().unwrap(),
1063                dst_buffer.vk_buffer().unwrap(),
1064                params,
1065            ),
1066            #[cfg(feature = "rafx-metal")]
1067            RafxCommandBuffer::Metal(inner) => inner.cmd_copy_buffer_to_buffer(
1068                src_buffer.metal_buffer().unwrap(),
1069                dst_buffer.metal_buffer().unwrap(),
1070                params,
1071            ),
1072            #[cfg(feature = "rafx-gles2")]
1073            RafxCommandBuffer::Gles2(inner) => inner.cmd_copy_buffer_to_buffer(
1074                src_buffer.gles2_buffer().unwrap(),
1075                dst_buffer.gles2_buffer().unwrap(),
1076                params,
1077            ),
1078            #[cfg(feature = "rafx-gles3")]
1079            RafxCommandBuffer::Gles3(inner) => inner.cmd_copy_buffer_to_buffer(
1080                src_buffer.gles3_buffer().unwrap(),
1081                dst_buffer.gles3_buffer().unwrap(),
1082                params,
1083            ),
1084            #[cfg(any(
1085                feature = "rafx-empty",
1086                not(any(
1087                    feature = "rafx-dx12",
1088                    feature = "rafx-metal",
1089                    feature = "rafx-vulkan",
1090                    feature = "rafx-gles2",
1091                    feature = "rafx-gles3"
1092                ))
1093            ))]
1094            RafxCommandBuffer::Empty(inner) => inner.cmd_copy_buffer_to_buffer(
1095                src_buffer.empty_buffer().unwrap(),
1096                dst_buffer.empty_buffer().unwrap(),
1097                params,
1098            ),
1099        }
1100    }
1101
1102    /// Copy the contents of a buffer into a texture. This occurs on the GPU and allows modifying
1103    /// resources that are not accessible to the CPU.
1104    pub fn cmd_copy_buffer_to_texture(
1105        &self,
1106        src_buffer: &RafxBuffer,
1107        dst_texture: &RafxTexture,
1108        params: &RafxCmdCopyBufferToTextureParams,
1109    ) -> RafxResult<()> {
1110        match self {
1111            #[cfg(feature = "rafx-dx12")]
1112            RafxCommandBuffer::Dx12(inner) => inner.cmd_copy_buffer_to_texture(
1113                src_buffer.dx12_buffer().unwrap(),
1114                dst_texture.dx12_texture().unwrap(),
1115                params,
1116            ),
1117            #[cfg(feature = "rafx-vulkan")]
1118            RafxCommandBuffer::Vk(inner) => inner.cmd_copy_buffer_to_texture(
1119                src_buffer.vk_buffer().unwrap(),
1120                dst_texture.vk_texture().unwrap(),
1121                params,
1122            ),
1123            #[cfg(feature = "rafx-metal")]
1124            RafxCommandBuffer::Metal(inner) => inner.cmd_copy_buffer_to_texture(
1125                src_buffer.metal_buffer().unwrap(),
1126                dst_texture.metal_texture().unwrap(),
1127                params,
1128            ),
1129            #[cfg(feature = "rafx-gles2")]
1130            RafxCommandBuffer::Gles2(inner) => inner.cmd_copy_buffer_to_texture(
1131                src_buffer.gles2_buffer().unwrap(),
1132                dst_texture.gles2_texture().unwrap(),
1133                params,
1134            ),
1135            #[cfg(feature = "rafx-gles3")]
1136            RafxCommandBuffer::Gles3(inner) => inner.cmd_copy_buffer_to_texture(
1137                src_buffer.gles3_buffer().unwrap(),
1138                dst_texture.gles3_texture().unwrap(),
1139                params,
1140            ),
1141            #[cfg(any(
1142                feature = "rafx-empty",
1143                not(any(
1144                    feature = "rafx-dx12",
1145                    feature = "rafx-metal",
1146                    feature = "rafx-vulkan",
1147                    feature = "rafx-gles2",
1148                    feature = "rafx-gles3"
1149                ))
1150            ))]
1151            RafxCommandBuffer::Empty(inner) => inner.cmd_copy_buffer_to_texture(
1152                src_buffer.empty_buffer().unwrap(),
1153                dst_texture.empty_texture().unwrap(),
1154                params,
1155            ),
1156        }
1157    }
1158
1159    /// Copy the contents of a buffer into a texture. This occurs on the GPU and allows modifying
1160    /// resources that are not accessible to the CPU.
1161    pub fn cmd_copy_texture_to_texture(
1162        &self,
1163        src_texture: &RafxTexture,
1164        dst_texture: &RafxTexture,
1165        params: &RafxCmdCopyTextureToTextureParams,
1166    ) -> RafxResult<()> {
1167        match self {
1168            #[cfg(feature = "rafx-dx12")]
1169            RafxCommandBuffer::Dx12(inner) => inner.cmd_copy_texture_to_texture(
1170                src_texture.dx12_texture().unwrap(),
1171                dst_texture.dx12_texture().unwrap(),
1172                params,
1173            ),
1174            #[cfg(feature = "rafx-vulkan")]
1175            RafxCommandBuffer::Vk(inner) => inner.cmd_copy_texture_to_texture(
1176                src_texture.vk_texture().unwrap(),
1177                dst_texture.vk_texture().unwrap(),
1178                params,
1179            ),
1180            #[cfg(feature = "rafx-metal")]
1181            RafxCommandBuffer::Metal(inner) => inner.cmd_copy_texture_to_texture(
1182                src_texture.metal_texture().unwrap(),
1183                dst_texture.metal_texture().unwrap(),
1184                params,
1185            ),
1186            #[cfg(feature = "rafx-gles2")]
1187            RafxCommandBuffer::Gles2(_inner) => {
1188                let _ = src_texture;
1189                let _ = dst_texture;
1190                let _ = params;
1191                unimplemented!()
1192            }
1193            #[cfg(feature = "rafx-gles3")]
1194            RafxCommandBuffer::Gles3(_inner) => {
1195                let _ = src_texture;
1196                let _ = dst_texture;
1197                let _ = params;
1198                unimplemented!()
1199            }
1200            #[cfg(any(
1201                feature = "rafx-empty",
1202                not(any(
1203                    feature = "rafx-dx12",
1204                    feature = "rafx-metal",
1205                    feature = "rafx-vulkan",
1206                    feature = "rafx-gles2",
1207                    feature = "rafx-gles3"
1208                ))
1209            ))]
1210            RafxCommandBuffer::Empty(inner) => inner.cmd_copy_texture_to_texture(
1211                src_texture.empty_texture().unwrap(),
1212                dst_texture.empty_texture().unwrap(),
1213                params,
1214            ),
1215        }
1216    }
1217
1218    /// Begins labeling the following commands with the given name until [`cmd_pop_group_debug_name`] is called.
1219    /// This is useful for grouping together commands for use in a debugger.
1220    pub fn cmd_push_group_debug_name(
1221        &self,
1222        _name: impl AsRef<str>,
1223    ) {
1224        match self {
1225            #[cfg(feature = "rafx-dx12")]
1226            RafxCommandBuffer::Dx12(inner) => inner.cmd_push_group_debug_name(_name),
1227            #[cfg(feature = "rafx-vulkan")]
1228            RafxCommandBuffer::Vk(inner) => inner.cmd_push_group_debug_name(_name),
1229            #[cfg(feature = "rafx-metal")]
1230            RafxCommandBuffer::Metal(inner) => inner.cmd_push_group_debug_name(_name),
1231            #[cfg(feature = "rafx-gles2")]
1232            RafxCommandBuffer::Gles2(_) => {}
1233            #[cfg(feature = "rafx-gles3")]
1234            RafxCommandBuffer::Gles3(_) => {}
1235            #[cfg(any(
1236                feature = "rafx-empty",
1237                not(any(
1238                    feature = "rafx-dx12",
1239                    feature = "rafx-metal",
1240                    feature = "rafx-vulkan",
1241                    feature = "rafx-gles2",
1242                    feature = "rafx-gles3"
1243                ))
1244            ))]
1245            RafxCommandBuffer::Empty(inner) => inner.cmd_push_group_debug_name(_name),
1246        }
1247    }
1248
1249    /// Ends a debug label that was started with [`cmd_push_group_debug_name`].
1250    pub fn cmd_pop_group_debug_name(&self) {
1251        match self {
1252            #[cfg(feature = "rafx-dx12")]
1253            RafxCommandBuffer::Dx12(inner) => inner.cmd_pop_group_debug_name(),
1254            #[cfg(feature = "rafx-vulkan")]
1255            RafxCommandBuffer::Vk(inner) => inner.cmd_pop_group_debug_name(),
1256            #[cfg(feature = "rafx-metal")]
1257            RafxCommandBuffer::Metal(inner) => inner.cmd_pop_group_debug_name(),
1258            #[cfg(feature = "rafx-gles2")]
1259            RafxCommandBuffer::Gles2(_) => {}
1260            #[cfg(feature = "rafx-gles3")]
1261            RafxCommandBuffer::Gles3(_) => {}
1262            #[cfg(any(
1263                feature = "rafx-empty",
1264                not(any(
1265                    feature = "rafx-dx12",
1266                    feature = "rafx-metal",
1267                    feature = "rafx-vulkan",
1268                    feature = "rafx-gles2",
1269                    feature = "rafx-gles3"
1270                ))
1271            ))]
1272            RafxCommandBuffer::Empty(inner) => inner.cmd_pop_group_debug_name(),
1273        }
1274    }
1275
1276    /// Get the underlying vulkan API object. This provides access to any internally created
1277    /// vulkan objects.
1278    #[cfg(feature = "rafx-dx12")]
1279    pub fn dx12_command_buffer(&self) -> Option<&RafxCommandBufferDx12> {
1280        match self {
1281            #[cfg(feature = "rafx-dx12")]
1282            RafxCommandBuffer::Dx12(inner) => Some(inner),
1283            #[cfg(feature = "rafx-vulkan")]
1284            RafxCommandBuffer::Vk(_) => None,
1285            #[cfg(feature = "rafx-metal")]
1286            RafxCommandBuffer::Metal(_) => None,
1287            #[cfg(feature = "rafx-gles2")]
1288            RafxCommandBuffer::Gles2(_) => None,
1289            #[cfg(feature = "rafx-gles3")]
1290            RafxCommandBuffer::Gles3(_) => None,
1291            #[cfg(any(
1292                feature = "rafx-empty",
1293                not(any(
1294                    feature = "rafx-dx12",
1295                    feature = "rafx-metal",
1296                    feature = "rafx-vulkan",
1297                    feature = "rafx-gles2",
1298                    feature = "rafx-gles3"
1299                ))
1300            ))]
1301            RafxCommandBuffer::Empty(_) => None,
1302        }
1303    }
1304
1305    /// Get the underlying vulkan API object. This provides access to any internally created
1306    /// vulkan objects.
1307    #[cfg(feature = "rafx-vulkan")]
1308    pub fn vk_command_buffer(&self) -> Option<&RafxCommandBufferVulkan> {
1309        match self {
1310            #[cfg(feature = "rafx-dx12")]
1311            RafxCommandBuffer::Dx12(_) => None,
1312            #[cfg(feature = "rafx-vulkan")]
1313            RafxCommandBuffer::Vk(inner) => Some(inner),
1314            #[cfg(feature = "rafx-metal")]
1315            RafxCommandBuffer::Metal(_) => None,
1316            #[cfg(feature = "rafx-gles2")]
1317            RafxCommandBuffer::Gles2(_) => None,
1318            #[cfg(feature = "rafx-gles3")]
1319            RafxCommandBuffer::Gles3(_) => None,
1320            #[cfg(any(
1321                feature = "rafx-empty",
1322                not(any(
1323                    feature = "rafx-dx12",
1324                    feature = "rafx-metal",
1325                    feature = "rafx-vulkan",
1326                    feature = "rafx-gles2",
1327                    feature = "rafx-gles3"
1328                ))
1329            ))]
1330            RafxCommandBuffer::Empty(_) => None,
1331        }
1332    }
1333
1334    /// Get the underlying metal API object. This provides access to any internally created
1335    /// metal objects.
1336    #[cfg(feature = "rafx-metal")]
1337    pub fn metal_command_buffer(&self) -> Option<&RafxCommandBufferMetal> {
1338        match self {
1339            #[cfg(feature = "rafx-dx12")]
1340            RafxCommandBuffer::Dx12(_) => None,
1341            #[cfg(feature = "rafx-vulkan")]
1342            RafxCommandBuffer::Vk(_) => None,
1343            #[cfg(feature = "rafx-metal")]
1344            RafxCommandBuffer::Metal(inner) => Some(inner),
1345            #[cfg(feature = "rafx-gles2")]
1346            RafxCommandBuffer::Gles2(_) => None,
1347            #[cfg(feature = "rafx-gles3")]
1348            RafxCommandBuffer::Gles3(_) => None,
1349            #[cfg(any(
1350                feature = "rafx-empty",
1351                not(any(
1352                    feature = "rafx-dx12",
1353                    feature = "rafx-metal",
1354                    feature = "rafx-vulkan",
1355                    feature = "rafx-gles2",
1356                    feature = "rafx-gles3"
1357                ))
1358            ))]
1359            RafxCommandBuffer::Empty(_) => None,
1360        }
1361    }
1362
1363    /// Get the underlying gl API object. This provides access to any internally created
1364    /// metal objects.
1365    #[cfg(feature = "rafx-gles2")]
1366    pub fn gles2_command_buffer(&self) -> Option<&RafxCommandBufferGles2> {
1367        match self {
1368            #[cfg(feature = "rafx-dx12")]
1369            RafxCommandBuffer::Dx12(_) => None,
1370            #[cfg(feature = "rafx-vulkan")]
1371            RafxCommandBuffer::Vk(_) => None,
1372            #[cfg(feature = "rafx-metal")]
1373            RafxCommandBuffer::Metal(_) => None,
1374            #[cfg(feature = "rafx-gles2")]
1375            RafxCommandBuffer::Gles2(inner) => Some(inner),
1376            #[cfg(feature = "rafx-gles3")]
1377            RafxCommandBuffer::Gles3(_) => None,
1378            #[cfg(any(
1379                feature = "rafx-empty",
1380                not(any(
1381                    feature = "rafx-dx12",
1382                    feature = "rafx-metal",
1383                    feature = "rafx-vulkan",
1384                    feature = "rafx-gles2",
1385                    feature = "rafx-gles3"
1386                ))
1387            ))]
1388            RafxCommandBuffer::Empty(_) => None,
1389        }
1390    }
1391
1392    /// Get the underlying gl API object. This provides access to any internally created
1393    /// metal objects.
1394    #[cfg(feature = "rafx-gles3")]
1395    pub fn gles3_command_buffer(&self) -> Option<&RafxCommandBufferGles3> {
1396        match self {
1397            #[cfg(feature = "rafx-dx12")]
1398            RafxCommandBuffer::Dx12(_) => None,
1399            #[cfg(feature = "rafx-vulkan")]
1400            RafxCommandBuffer::Vk(_) => None,
1401            #[cfg(feature = "rafx-metal")]
1402            RafxCommandBuffer::Metal(_) => None,
1403            #[cfg(feature = "rafx-gles2")]
1404            RafxCommandBuffer::Gles2(_) => None,
1405            #[cfg(feature = "rafx-gles3")]
1406            RafxCommandBuffer::Gles3(inner) => Some(inner),
1407            #[cfg(any(
1408                feature = "rafx-empty",
1409                not(any(
1410                    feature = "rafx-dx12",
1411                    feature = "rafx-metal",
1412                    feature = "rafx-vulkan",
1413                    feature = "rafx-gles2",
1414                    feature = "rafx-gles3"
1415                ))
1416            ))]
1417            RafxCommandBuffer::Empty(_) => None,
1418        }
1419    }
1420
1421    /// Get the underlying metal API object. This provides access to any internally created
1422    /// metal objects.
1423    #[cfg(any(
1424        feature = "rafx-empty",
1425        not(any(
1426            feature = "rafx-dx12",
1427            feature = "rafx-metal",
1428            feature = "rafx-vulkan",
1429            feature = "rafx-gles2",
1430            feature = "rafx-gles3"
1431        ))
1432    ))]
1433    pub fn empty_command_buffer(&self) -> Option<&RafxCommandBufferEmpty> {
1434        match self {
1435            #[cfg(feature = "rafx-dx12")]
1436            RafxCommandBuffer::Dx12(_) => None,
1437            #[cfg(feature = "rafx-vulkan")]
1438            RafxCommandBuffer::Vk(_) => None,
1439            #[cfg(feature = "rafx-metal")]
1440            RafxCommandBuffer::Metal(_) => None,
1441            #[cfg(feature = "rafx-gles2")]
1442            RafxCommandBuffer::Gles2(_) => None,
1443            #[cfg(feature = "rafx-gles3")]
1444            RafxCommandBuffer::Gles3(_) => None,
1445            #[cfg(any(
1446                feature = "rafx-empty",
1447                not(any(
1448                    feature = "rafx-dx12",
1449                    feature = "rafx-metal",
1450                    feature = "rafx-vulkan",
1451                    feature = "rafx-gles2",
1452                    feature = "rafx-gles3"
1453                ))
1454            ))]
1455            RafxCommandBuffer::Empty(inner) => Some(inner),
1456        }
1457    }
1458}