gfx_hal/command/mod.rs
1//! Command buffers.
2//!
3//! A command buffer collects a list of commands to be submitted to the device.
4//!
5//! Each command buffer has specific capabilities for graphics, compute or transfer operations,
6//! and can be either a *primary* command buffer or a *secondary* command buffer.
7//!
8//! Operations are always initiated by a primary command buffer,
9//! but a primary command buffer can contain calls to secondary command buffers
10//! that contain snippets of commands that do specific things, similar to function calls.
11//!
12//! All the possible commands are exposed by the [`CommandBuffer`][CommandBuffer] trait.
13
14// TODO: Document pipelines and subpasses better.
15
16mod clear;
17mod structs;
18
19use crate::{
20 buffer,
21 image::{Filter, Layout, SubresourceRange},
22 memory::{Barrier, Dependencies},
23 pass, pso, query, Backend, DrawCount, IndexCount, IndexType, InstanceCount, TaskCount,
24 VertexCount, VertexOffset, WorkGroupCount,
25};
26
27use std::{any::Any, fmt, ops::Range};
28
29pub use self::clear::*;
30pub use self::structs::*;
31
32/// Offset for dynamic descriptors.
33pub type DescriptorSetOffset = u32;
34
35bitflags! {
36 /// Option flags for various command buffer settings.
37 #[derive(Default)]
38 pub struct CommandBufferFlags: u32 {
39 /// Says that the command buffer will be recorded, submitted only once, and then reset and re-filled
40 /// for another submission.
41 const ONE_TIME_SUBMIT = 0x1;
42
43 /// If set on a secondary command buffer, it says the command buffer takes place entirely inside
44 /// a render pass. Ignored on primary command buffer.
45 const RENDER_PASS_CONTINUE = 0x2;
46
47 /// Says that a command buffer can be recorded into multiple primary command buffers,
48 /// and submitted to a queue while it is still pending.
49 const SIMULTANEOUS_USE = 0x4;
50 }
51}
52
53/// An enum that indicates whether a command buffer is primary or secondary.
54#[derive(Clone, Copy, Debug, PartialEq)]
55pub enum Level {
56 /// Can be submitted to a queue for execution, but cannot be called from other
57 /// command buffers.
58 Primary,
59 /// Cannot be submitted directly, but can be called from primary command buffers.
60 Secondary,
61}
62
63/// Specifies how commands for the following render passes will be recorded.
64#[derive(Debug)]
65pub enum SubpassContents {
66 /// Contents of the subpass will be inline in the command buffer,
67 /// NOT in secondary command buffers.
68 Inline,
69 /// Contents of the subpass will be in secondary command buffers, and
70 /// the primary command buffer will only contain `execute_command()` calls
71 /// until the subpass or render pass is complete.
72 SecondaryBuffers,
73}
74
75/// A render attachment provided to `begin_render_pass`.
76#[derive(Debug)]
77pub struct RenderAttachmentInfo<'a, B: Backend> {
78 /// View of the attachment image.
79 pub image_view: &'a B::ImageView,
80 /// Clear value, if needed.
81 pub clear_value: ClearValue,
82}
83
84#[allow(missing_docs)]
85#[derive(Debug)]
86pub struct CommandBufferInheritanceInfo<'a, B: Backend> {
87 pub subpass: Option<pass::Subpass<'a, B>>,
88 pub framebuffer: Option<&'a B::Framebuffer>,
89 pub occlusion_query_enable: bool,
90 pub occlusion_query_flags: query::ControlFlags,
91 pub pipeline_statistics: query::PipelineStatistic,
92}
93
94impl<'a, B: Backend> Default for CommandBufferInheritanceInfo<'a, B> {
95 fn default() -> Self {
96 CommandBufferInheritanceInfo {
97 subpass: None,
98 framebuffer: None,
99 occlusion_query_enable: false,
100 occlusion_query_flags: query::ControlFlags::empty(),
101 pipeline_statistics: query::PipelineStatistic::empty(),
102 }
103 }
104}
105
106/// A trait that describes all the operations that must be
107/// provided by a `Backend`'s command buffer.
108pub trait CommandBuffer<B: Backend>: fmt::Debug + Any + Send + Sync {
109 /// Begins recording commands to a command buffer.
110 unsafe fn begin(
111 &mut self,
112 flags: CommandBufferFlags,
113 inheritance_info: CommandBufferInheritanceInfo<B>,
114 );
115
116 /// Begins recording a primary command buffer
117 /// (that has no inheritance information).
118 unsafe fn begin_primary(&mut self, flags: CommandBufferFlags) {
119 self.begin(flags, CommandBufferInheritanceInfo::default());
120 }
121
122 /// Finish recording commands to a command buffer.
123 unsafe fn finish(&mut self);
124
125 /// Empties the command buffer, optionally releasing all
126 /// resources from the commands that have been submitted.
127 unsafe fn reset(&mut self, release_resources: bool);
128
129 // TODO: This REALLY needs to be deeper, but it's complicated.
130 // Should probably be a whole book chapter on synchronization and stuff really.
131 /// Inserts a synchronization dependency between pipeline stages
132 /// in the command buffer.
133 unsafe fn pipeline_barrier<'a, T>(
134 &mut self,
135 stages: Range<pso::PipelineStage>,
136 dependencies: Dependencies,
137 barriers: T,
138 ) where
139 T: Iterator<Item = Barrier<'a, B>>;
140
141 /// Fill a buffer with the given `u32` value.
142 unsafe fn fill_buffer(&mut self, buffer: &B::Buffer, range: buffer::SubRange, data: u32);
143
144 /// Copy data from the given slice into a buffer.
145 unsafe fn update_buffer(&mut self, buffer: &B::Buffer, offset: buffer::Offset, data: &[u8]);
146
147 /// Clears an image to the given color/depth/stencil.
148 unsafe fn clear_image<T>(
149 &mut self,
150 image: &B::Image,
151 layout: Layout,
152 value: ClearValue,
153 subresource_ranges: T,
154 ) where
155 T: Iterator<Item = SubresourceRange>;
156
157 /// Takes an iterator of attachments and an iterator of rect's,
158 /// and clears the given rect's for *each* attachment.
159 unsafe fn clear_attachments<T, U>(&mut self, clears: T, rects: U)
160 where
161 T: Iterator<Item = AttachmentClear>,
162 U: Iterator<Item = pso::ClearRect>;
163
164 /// "Resolves" a multisampled image, converting it into a non-multisampled
165 /// image. Takes an iterator of regions to apply the resolution to.
166 unsafe fn resolve_image<T>(
167 &mut self,
168 src: &B::Image,
169 src_layout: Layout,
170 dst: &B::Image,
171 dst_layout: Layout,
172 regions: T,
173 ) where
174 T: Iterator<Item = ImageResolve>;
175
176 /// Copies regions from the source to destination image,
177 /// applying scaling, filtering and potentially format conversion.
178 unsafe fn blit_image<T>(
179 &mut self,
180 src: &B::Image,
181 src_layout: Layout,
182 dst: &B::Image,
183 dst_layout: Layout,
184 filter: Filter,
185 regions: T,
186 ) where
187 T: Iterator<Item = ImageBlit>;
188
189 /// Bind the index buffer view, making it the "current" one that draw commands
190 /// will operate on.
191 unsafe fn bind_index_buffer(
192 &mut self,
193 buffer: &B::Buffer,
194 sub: buffer::SubRange,
195 ty: IndexType,
196 );
197
198 /// Bind the vertex buffer set, making it the "current" one that draw commands
199 /// will operate on.
200 ///
201 /// Each buffer passed corresponds to the vertex input binding with the same index,
202 /// starting from an offset index `first_binding`. For example an iterator with
203 /// two items and `first_binding` of 1 would fill vertex buffer binding numbers
204 /// 1 and 2.
205 ///
206 /// This binding number refers only to binding points for vertex buffers and is
207 /// completely separate from the binding numbers of `Descriptor`s in `DescriptorSet`s.
208 /// It needs to match with the `VertexBufferDesc` and `AttributeDesc`s to which the
209 /// data from each bound vertex buffer should flow.
210 ///
211 /// The `buffers` iterator should yield the `Buffer` to bind, as well as a subrange,
212 /// in bytes, into that buffer where the vertex data that should be bound.
213 unsafe fn bind_vertex_buffers<'a, T>(&mut self, first_binding: pso::BufferIndex, buffers: T)
214 where
215 T: Iterator<Item = (&'a B::Buffer, buffer::SubRange)>;
216
217 /// Set the [viewport][crate::pso::Viewport] parameters for the rasterizer.
218 ///
219 /// Each viewport passed corresponds to the viewport with the same index,
220 /// starting from an offset index `first_viewport`.
221 ///
222 /// # Errors
223 ///
224 /// This function does not return an error. Invalid usage of this function
225 /// will result in undefined behavior.
226 ///
227 /// - Command buffer must be in recording state.
228 /// - Number of viewports must be between 1 and `max_viewports - first_viewport`.
229 /// - The first viewport must be less than `max_viewports`.
230 /// - Only queues with graphics capability support this function.
231 /// - The bound pipeline must not have baked viewport state.
232 /// - All viewports used by the pipeline must be specified before the first
233 /// draw call.
234 unsafe fn set_viewports<T>(&mut self, first_viewport: u32, viewports: T)
235 where
236 T: Iterator<Item = pso::Viewport>;
237
238 /// Set the scissor rectangles for the rasterizer.
239 ///
240 /// Each scissor corresponds to the viewport with the same index, starting
241 /// from an offset index `first_scissor`.
242 ///
243 /// # Errors
244 ///
245 /// This function does not return an error. Invalid usage of this function
246 /// will result in undefined behavior.
247 ///
248 /// - Command buffer must be in recording state.
249 /// - Number of scissors must be between 1 and `max_viewports - first_scissor`.
250 /// - The first scissor must be less than `max_viewports`.
251 /// - Only queues with graphics capability support this function.
252 /// - The bound pipeline must not have baked scissor state.
253 /// - All scissors used by the pipeline must be specified before the first draw
254 /// call.
255 unsafe fn set_scissors<T>(&mut self, first_scissor: u32, rects: T)
256 where
257 T: Iterator<Item = pso::Rect>;
258
259 /// Sets the stencil reference value for comparison operations and store operations.
260 /// Will be used on the LHS of stencil compare ops and as store value when the
261 /// store op is Reference.
262 unsafe fn set_stencil_reference(&mut self, faces: pso::Face, value: pso::StencilValue);
263
264 /// Sets the stencil read mask.
265 unsafe fn set_stencil_read_mask(&mut self, faces: pso::Face, value: pso::StencilValue);
266
267 /// Sets the stencil write mask.
268 unsafe fn set_stencil_write_mask(&mut self, faces: pso::Face, value: pso::StencilValue);
269
270 /// Set the blend constant values dynamically.
271 unsafe fn set_blend_constants(&mut self, color: pso::ColorValue);
272
273 /// Set the depth bounds test values dynamically.
274 unsafe fn set_depth_bounds(&mut self, bounds: Range<f32>);
275
276 /// Set the line width dynamically.
277 ///
278 /// Only valid to call if `Features::LINE_WIDTH` is enabled.
279 unsafe fn set_line_width(&mut self, width: f32);
280
281 /// Set the depth bias dynamically.
282 unsafe fn set_depth_bias(&mut self, depth_bias: pso::DepthBias);
283
284 /// Begins recording commands for a render pass on the given framebuffer.
285 ///
286 /// # Arguments
287 ///
288 /// * `render_area` - section of the framebuffer to render.
289 /// * `attachments` - iterator of [attachments][crate::command::RenderAttachmentInfo]
290 /// that has both the image views and the clear values
291 /// * `first_subpass` - specifies, for the first subpass, whether the
292 /// rendering commands are provided inline or whether the render
293 /// pass is composed of subpasses.
294 unsafe fn begin_render_pass<'a, T>(
295 &mut self,
296 render_pass: &B::RenderPass,
297 framebuffer: &B::Framebuffer,
298 render_area: pso::Rect,
299 attachments: T,
300 first_subpass: SubpassContents,
301 ) where
302 T: Iterator<Item = RenderAttachmentInfo<'a, B>>;
303
304 /// Steps to the next subpass in the current render pass.
305 unsafe fn next_subpass(&mut self, contents: SubpassContents);
306
307 /// Finishes recording commands for the current a render pass.
308 unsafe fn end_render_pass(&mut self);
309
310 /// Bind a graphics pipeline.
311 ///
312 /// # Errors
313 ///
314 /// This function does not return an error. Invalid usage of this function
315 /// will result in an error on `finish`.
316 ///
317 /// - Command buffer must be in recording state.
318 /// - Only queues with graphics capability support this function.
319 unsafe fn bind_graphics_pipeline(&mut self, pipeline: &B::GraphicsPipeline);
320
321 /// Takes an iterator of graphics `DescriptorSet`'s, and binds them to the command buffer.
322 /// `first_set` is the index that the first descriptor is mapped to in the command buffer.
323 unsafe fn bind_graphics_descriptor_sets<'a, I, J>(
324 &mut self,
325 layout: &B::PipelineLayout,
326 first_set: usize,
327 sets: I,
328 offsets: J,
329 ) where
330 I: Iterator<Item = &'a B::DescriptorSet>,
331 J: Iterator<Item = DescriptorSetOffset>;
332
333 /// Bind a compute pipeline.
334 ///
335 /// # Errors
336 ///
337 /// This function does not return an error. Invalid usage of this function
338 /// will result in an error on `finish`.
339 ///
340 /// - Command buffer must be in recording state.
341 /// - Only queues with compute capability support this function.
342 unsafe fn bind_compute_pipeline(&mut self, pipeline: &B::ComputePipeline);
343
344 /// Takes an iterator of compute `DescriptorSet`'s, and binds them to the command buffer,
345 /// `first_set` is the index that the first descriptor is mapped to in the command buffer.
346 unsafe fn bind_compute_descriptor_sets<'a, I, J>(
347 &mut self,
348 layout: &B::PipelineLayout,
349 first_set: usize,
350 sets: I,
351 offsets: J,
352 ) where
353 I: Iterator<Item = &'a B::DescriptorSet>,
354 J: Iterator<Item = DescriptorSetOffset>;
355
356 /// Execute a workgroup in the compute pipeline. `x`, `y` and `z` are the
357 /// number of local workgroups to dispatch along each "axis"; a total of `x`*`y`*`z`
358 /// local workgroups will be created.
359 ///
360 /// # Errors
361 ///
362 /// This function does not return an error. Invalid usage of this function
363 /// will result in an error on `finish`.
364 ///
365 /// - Command buffer must be in recording state.
366 /// - A compute pipeline must be bound using `bind_compute_pipeline`.
367 /// - Only queues with compute capability support this function.
368 /// - This function must be called outside of a render pass.
369 /// - `count` must be less than or equal to `Limits::max_compute_work_group_count`
370 ///
371 /// TODO:
372 unsafe fn dispatch(&mut self, count: WorkGroupCount);
373
374 /// Works similarly to `dispatch()` but reads parameters from the given
375 /// buffer during execution.
376 unsafe fn dispatch_indirect(&mut self, buffer: &B::Buffer, offset: buffer::Offset);
377
378 /// Adds a command to copy regions from the source to destination buffer.
379 unsafe fn copy_buffer<T>(&mut self, src: &B::Buffer, dst: &B::Buffer, regions: T)
380 where
381 T: Iterator<Item = BufferCopy>;
382
383 /// Copies regions from the source to the destination images, which
384 /// have the given layouts. No format conversion is done; the source and destination
385 /// `Layout`'s **must** have the same sized image formats (such as `Rgba8Unorm` and
386 /// `R32`, both of which are 32 bits).
387 unsafe fn copy_image<T>(
388 &mut self,
389 src: &B::Image,
390 src_layout: Layout,
391 dst: &B::Image,
392 dst_layout: Layout,
393 regions: T,
394 ) where
395 T: Iterator<Item = ImageCopy>;
396
397 /// Copies regions from the source buffer to the destination image.
398 unsafe fn copy_buffer_to_image<T>(
399 &mut self,
400 src: &B::Buffer,
401 dst: &B::Image,
402 dst_layout: Layout,
403 regions: T,
404 ) where
405 T: Iterator<Item = BufferImageCopy>;
406
407 /// Copies regions from the source image to the destination buffer.
408 unsafe fn copy_image_to_buffer<T>(
409 &mut self,
410 src: &B::Image,
411 src_layout: Layout,
412 dst: &B::Buffer,
413 regions: T,
414 ) where
415 T: Iterator<Item = BufferImageCopy>;
416
417 // TODO: This explanation needs improvement.
418 /// Performs a non-indexed drawing operation, fetching vertex attributes
419 /// from the currently bound vertex buffers. It performs instanced
420 /// drawing, drawing `instances.len()`
421 /// times with an `instanceIndex` starting with the start of the range.
422 unsafe fn draw(&mut self, vertices: Range<VertexCount>, instances: Range<InstanceCount>);
423
424 /// Performs indexed drawing, drawing the range of indices
425 /// given by the current index buffer and any bound vertex buffers.
426 /// `base_vertex` specifies the vertex offset corresponding to index 0.
427 /// That is, the offset into the vertex buffer is `(current_index + base_vertex)`
428 ///
429 /// It also performs instanced drawing, identical to `draw()`.
430 unsafe fn draw_indexed(
431 &mut self,
432 indices: Range<IndexCount>,
433 base_vertex: VertexOffset,
434 instances: Range<InstanceCount>,
435 );
436
437 /// Functions identically to `draw()`, except the parameters are read
438 /// from the given buffer, starting at `offset` and increasing `stride`
439 /// bytes with each successive draw. Performs `draw_count` draws total.
440 /// `draw_count` may be zero.
441 ///
442 /// Each draw command in the buffer is a series of 4 `u32` values specifying,
443 /// in order, the number of vertices to draw, the number of instances to draw,
444 /// the index of the first vertex to draw, and the instance ID of the first
445 /// instance to draw.
446 unsafe fn draw_indirect(
447 &mut self,
448 buffer: &B::Buffer,
449 offset: buffer::Offset,
450 draw_count: DrawCount,
451 stride: buffer::Stride,
452 );
453
454 /// Like `draw_indirect()`, this does indexed drawing a la `draw_indexed()` but
455 /// reads the draw parameters out of the given buffer.
456 ///
457 /// Each draw command in the buffer is a series of 5 values specifying,
458 /// in order, the number of indices, the number of instances, the first index,
459 /// the vertex offset, and the first instance. All are `u32`'s except
460 /// the vertex offset, which is an `i32`.
461 unsafe fn draw_indexed_indirect(
462 &mut self,
463 buffer: &B::Buffer,
464 offset: buffer::Offset,
465 draw_count: DrawCount,
466 stride: buffer::Stride,
467 );
468
469 /// Functions identically to `draw_indirect()`, except the amount of draw
470 /// calls are specified by the u32 in `count_buffer` at `count_buffer_offset`.
471 /// There is a limit of `max_draw_count` invocations.
472 ///
473 /// Each draw command in the buffer is a series of 4 `u32` values specifying,
474 /// in order, the number of vertices to draw, the number of instances to draw,
475 /// the index of the first vertex to draw, and the instance ID of the first
476 /// instance to draw.
477 unsafe fn draw_indirect_count(
478 &mut self,
479 _buffer: &B::Buffer,
480 _offset: buffer::Offset,
481 _count_buffer: &B::Buffer,
482 _count_buffer_offset: buffer::Offset,
483 _max_draw_count: u32,
484 _stride: buffer::Stride,
485 );
486
487 /// Functions identically to `draw_indexed_indirect()`, except the amount of draw
488 /// calls are specified by the u32 in `count_buffer` at `count_buffer_offset`.
489 /// There is a limit of `max_draw_count` invocations.
490 ///
491 /// Each draw command in the buffer is a series of 5 values specifying,
492 /// in order, the number of indices, the number of instances, the first index,
493 /// the vertex offset, and the first instance. All are `u32`'s except
494 /// the vertex offset, which is an `i32`.
495 unsafe fn draw_indexed_indirect_count(
496 &mut self,
497 _buffer: &B::Buffer,
498 _offset: buffer::Offset,
499 _count_buffer: &B::Buffer,
500 _count_buffer_offset: buffer::Offset,
501 _max_draw_count: u32,
502 _stride: buffer::Stride,
503 );
504
505 /// Dispatches `task_count` of threads. Similar to compute dispatch.
506 unsafe fn draw_mesh_tasks(&mut self, task_count: TaskCount, first_task: TaskCount);
507
508 /// Indirect version of `draw_mesh_tasks`. Analogous to `draw_indirect`, but for mesh shaders.
509 unsafe fn draw_mesh_tasks_indirect(
510 &mut self,
511 buffer: &B::Buffer,
512 offset: buffer::Offset,
513 draw_count: DrawCount,
514 stride: buffer::Stride,
515 );
516
517 /// Like `draw_mesh_tasks_indirect` except that the draw count is read by
518 /// the device from a buffer during execution. The command will read an
519 /// unsigned 32-bit integer from `count_buffer` located at `count_buffer_offset`
520 /// and use this as the draw count.
521 unsafe fn draw_mesh_tasks_indirect_count(
522 &mut self,
523 buffer: &B::Buffer,
524 offset: buffer::Offset,
525 count_buffer: &B::Buffer,
526 count_buffer_offset: buffer::Offset,
527 max_draw_count: DrawCount,
528 stride: buffer::Stride,
529 );
530
531 /// Signals an event once all specified stages of the shader pipeline have completed.
532 unsafe fn set_event(&mut self, event: &B::Event, stages: pso::PipelineStage);
533
534 /// Resets an event once all specified stages of the shader pipeline have completed.
535 unsafe fn reset_event(&mut self, event: &B::Event, stages: pso::PipelineStage);
536
537 /// Waits at some shader stage(s) until all events have been signalled.
538 ///
539 /// - `src_stages` specifies the shader pipeline stages in which the events were signalled.
540 /// - `dst_stages` specifies the shader pipeline stages at which execution should wait.
541 /// - `barriers` specifies a series of memory barriers to be executed before pipeline execution
542 /// resumes.
543 unsafe fn wait_events<'a, I, J>(
544 &mut self,
545 events: I,
546 stages: Range<pso::PipelineStage>,
547 barriers: J,
548 ) where
549 I: Iterator<Item = &'a B::Event>,
550 J: Iterator<Item = Barrier<'a, B>>;
551
552 /// Begins a query operation. Queries count operations or record timestamps
553 /// resulting from commands that occur between the beginning and end of the query,
554 /// and save the results to the query pool.
555 unsafe fn begin_query(&mut self, query: query::Query<B>, flags: query::ControlFlags);
556
557 /// End a query.
558 unsafe fn end_query(&mut self, query: query::Query<B>);
559
560 /// Reset/clear the values in the given range of the query pool.
561 unsafe fn reset_query_pool(&mut self, pool: &B::QueryPool, queries: Range<query::Id>);
562
563 /// Copy query results into a buffer.
564 unsafe fn copy_query_pool_results(
565 &mut self,
566 pool: &B::QueryPool,
567 queries: Range<query::Id>,
568 buffer: &B::Buffer,
569 offset: buffer::Offset,
570 stride: buffer::Stride,
571 flags: query::ResultFlags,
572 );
573
574 /// Requests a timestamp to be written.
575 unsafe fn write_timestamp(&mut self, stage: pso::PipelineStage, query: query::Query<B>);
576
577 /// Modify constant data in a graphics pipeline. Push constants are intended to modify data in a
578 /// pipeline more quickly than a updating the values inside a descriptor set.
579 ///
580 /// Push constants must be aligned to 4 bytes, and to guarantee alignment, this function takes a
581 /// `&[u32]` instead of a `&[u8]`. Note that the offset is still specified in units of bytes.
582 unsafe fn push_graphics_constants(
583 &mut self,
584 layout: &B::PipelineLayout,
585 stages: pso::ShaderStageFlags,
586 offset: u32,
587 constants: &[u32],
588 );
589
590 /// Modify constant data in a compute pipeline. Push constants are intended to modify data in a
591 /// pipeline more quickly than a updating the values inside a descriptor set.
592 ///
593 /// Push constants must be aligned to 4 bytes, and to guarantee alignment, this function takes a
594 /// `&[u32]` instead of a `&[u8]`. Note that the offset is still specified in units of bytes.
595 unsafe fn push_compute_constants(
596 &mut self,
597 layout: &B::PipelineLayout,
598 offset: u32,
599 constants: &[u32],
600 );
601
602 /// Execute the given secondary command buffers.
603 unsafe fn execute_commands<'a, T>(&mut self, cmd_buffers: T)
604 where
605 T: Iterator<Item = &'a B::CommandBuffer>;
606
607 /// Debug mark the current spot in the command buffer.
608 unsafe fn insert_debug_marker(&mut self, name: &str, color: u32);
609 /// Start a debug marker at the current place in the command buffer.
610 unsafe fn begin_debug_marker(&mut self, name: &str, color: u32);
611 /// End the last started debug marker scope.
612 unsafe fn end_debug_marker(&mut self);
613}