Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_render/src/render_phase/draw_state.rs
6596 views
1
use crate::{
2
diagnostic::internal::{Pass, PassKind, WritePipelineStatistics, WriteTimestamp},
3
render_resource::{
4
BindGroup, BindGroupId, Buffer, BufferId, BufferSlice, RenderPipeline, RenderPipelineId,
5
ShaderStages,
6
},
7
renderer::RenderDevice,
8
};
9
use bevy_camera::Viewport;
10
use bevy_color::LinearRgba;
11
use bevy_utils::default;
12
use core::ops::Range;
13
use wgpu::{IndexFormat, QuerySet, RenderPass};
14
15
#[cfg(feature = "detailed_trace")]
16
use tracing::trace;
17
18
/// Tracks the state of a [`TrackedRenderPass`].
19
///
20
/// This is used to skip redundant operations on the [`TrackedRenderPass`] (e.g. setting an already
21
/// set pipeline, binding an already bound bind group). These operations can otherwise be fairly
22
/// costly due to IO to the GPU, so deduplicating these calls results in a speedup.
23
#[derive(Debug, Default)]
24
struct DrawState {
25
pipeline: Option<RenderPipelineId>,
26
bind_groups: Vec<(Option<BindGroupId>, Vec<u32>)>,
27
/// List of vertex buffers by [`BufferId`], offset, and size. See [`DrawState::buffer_slice_key`]
28
vertex_buffers: Vec<Option<(BufferId, u64, u64)>>,
29
index_buffer: Option<(BufferId, u64, IndexFormat)>,
30
31
/// Stores whether this state is populated or empty for quick state invalidation
32
stores_state: bool,
33
}
34
35
impl DrawState {
36
/// Marks the `pipeline` as bound.
37
fn set_pipeline(&mut self, pipeline: RenderPipelineId) {
38
// TODO: do these need to be cleared?
39
// self.bind_groups.clear();
40
// self.vertex_buffers.clear();
41
// self.index_buffer = None;
42
self.pipeline = Some(pipeline);
43
self.stores_state = true;
44
}
45
46
/// Checks, whether the `pipeline` is already bound.
47
fn is_pipeline_set(&self, pipeline: RenderPipelineId) -> bool {
48
self.pipeline == Some(pipeline)
49
}
50
51
/// Marks the `bind_group` as bound to the `index`.
52
fn set_bind_group(&mut self, index: usize, bind_group: BindGroupId, dynamic_indices: &[u32]) {
53
let group = &mut self.bind_groups[index];
54
group.0 = Some(bind_group);
55
group.1.clear();
56
group.1.extend(dynamic_indices);
57
self.stores_state = true;
58
}
59
60
/// Checks, whether the `bind_group` is already bound to the `index`.
61
fn is_bind_group_set(
62
&self,
63
index: usize,
64
bind_group: BindGroupId,
65
dynamic_indices: &[u32],
66
) -> bool {
67
if let Some(current_bind_group) = self.bind_groups.get(index) {
68
current_bind_group.0 == Some(bind_group) && dynamic_indices == current_bind_group.1
69
} else {
70
false
71
}
72
}
73
74
/// Marks the vertex `buffer` as bound to the `index`.
75
fn set_vertex_buffer(&mut self, index: usize, buffer_slice: BufferSlice) {
76
self.vertex_buffers[index] = Some(self.buffer_slice_key(&buffer_slice));
77
self.stores_state = true;
78
}
79
80
/// Checks, whether the vertex `buffer` is already bound to the `index`.
81
fn is_vertex_buffer_set(&self, index: usize, buffer_slice: &BufferSlice) -> bool {
82
if let Some(current) = self.vertex_buffers.get(index) {
83
*current == Some(self.buffer_slice_key(buffer_slice))
84
} else {
85
false
86
}
87
}
88
89
/// Returns the value used for checking whether `BufferSlice`s are equivalent.
90
fn buffer_slice_key(&self, buffer_slice: &BufferSlice) -> (BufferId, u64, u64) {
91
(
92
buffer_slice.id(),
93
buffer_slice.offset(),
94
buffer_slice.size(),
95
)
96
}
97
98
/// Marks the index `buffer` as bound.
99
fn set_index_buffer(&mut self, buffer: BufferId, offset: u64, index_format: IndexFormat) {
100
self.index_buffer = Some((buffer, offset, index_format));
101
self.stores_state = true;
102
}
103
104
/// Checks, whether the index `buffer` is already bound.
105
fn is_index_buffer_set(
106
&self,
107
buffer: BufferId,
108
offset: u64,
109
index_format: IndexFormat,
110
) -> bool {
111
self.index_buffer == Some((buffer, offset, index_format))
112
}
113
114
/// Resets tracking state
115
pub fn reset_tracking(&mut self) {
116
if !self.stores_state {
117
return;
118
}
119
self.pipeline = None;
120
self.bind_groups.iter_mut().for_each(|val| {
121
val.0 = None;
122
val.1.clear();
123
});
124
self.vertex_buffers.iter_mut().for_each(|val| {
125
*val = None;
126
});
127
self.index_buffer = None;
128
self.stores_state = false;
129
}
130
}
131
132
/// A [`RenderPass`], which tracks the current pipeline state to skip redundant operations.
133
///
134
/// It is used to set the current [`RenderPipeline`], [`BindGroup`]s and [`Buffer`]s.
135
/// After all requirements are specified, draw calls can be issued.
136
pub struct TrackedRenderPass<'a> {
137
pass: RenderPass<'a>,
138
state: DrawState,
139
}
140
141
impl<'a> TrackedRenderPass<'a> {
142
/// Tracks the supplied render pass.
143
pub fn new(device: &RenderDevice, pass: RenderPass<'a>) -> Self {
144
let limits = device.limits();
145
let max_bind_groups = limits.max_bind_groups as usize;
146
let max_vertex_buffers = limits.max_vertex_buffers as usize;
147
Self {
148
state: DrawState {
149
bind_groups: vec![(None, Vec::new()); max_bind_groups],
150
vertex_buffers: vec![None; max_vertex_buffers],
151
..default()
152
},
153
pass,
154
}
155
}
156
157
/// Returns the wgpu [`RenderPass`].
158
///
159
/// Function invalidates internal tracking state,
160
/// some redundant pipeline operations may not be skipped.
161
pub fn wgpu_pass(&mut self) -> &mut RenderPass<'a> {
162
self.state.reset_tracking();
163
&mut self.pass
164
}
165
166
/// Sets the active [`RenderPipeline`].
167
///
168
/// Subsequent draw calls will exhibit the behavior defined by the `pipeline`.
169
pub fn set_render_pipeline(&mut self, pipeline: &'a RenderPipeline) {
170
#[cfg(feature = "detailed_trace")]
171
trace!("set pipeline: {:?}", pipeline);
172
if self.state.is_pipeline_set(pipeline.id()) {
173
return;
174
}
175
self.pass.set_pipeline(pipeline);
176
self.state.set_pipeline(pipeline.id());
177
}
178
179
/// Sets the active bind group for a given bind group index. The bind group layout
180
/// in the active pipeline when any `draw()` function is called must match the layout of
181
/// this bind group.
182
///
183
/// If the bind group have dynamic offsets, provide them in binding order.
184
/// These offsets have to be aligned to [`WgpuLimits::min_uniform_buffer_offset_alignment`](crate::settings::WgpuLimits::min_uniform_buffer_offset_alignment)
185
/// or [`WgpuLimits::min_storage_buffer_offset_alignment`](crate::settings::WgpuLimits::min_storage_buffer_offset_alignment) appropriately.
186
pub fn set_bind_group(
187
&mut self,
188
index: usize,
189
bind_group: &'a BindGroup,
190
dynamic_uniform_indices: &[u32],
191
) {
192
if self
193
.state
194
.is_bind_group_set(index, bind_group.id(), dynamic_uniform_indices)
195
{
196
#[cfg(feature = "detailed_trace")]
197
trace!(
198
"set bind_group {} (already set): {:?} ({:?})",
199
index,
200
bind_group,
201
dynamic_uniform_indices
202
);
203
return;
204
}
205
#[cfg(feature = "detailed_trace")]
206
trace!(
207
"set bind_group {}: {:?} ({:?})",
208
index,
209
bind_group,
210
dynamic_uniform_indices
211
);
212
213
self.pass
214
.set_bind_group(index as u32, bind_group, dynamic_uniform_indices);
215
self.state
216
.set_bind_group(index, bind_group.id(), dynamic_uniform_indices);
217
}
218
219
/// Assign a vertex buffer to a slot.
220
///
221
/// Subsequent calls to [`draw`] and [`draw_indexed`] on this
222
/// [`TrackedRenderPass`] will use `buffer` as one of the source vertex buffers.
223
///
224
/// The `slot_index` refers to the index of the matching descriptor in
225
/// [`VertexState::buffers`](crate::render_resource::VertexState::buffers).
226
///
227
/// [`draw`]: TrackedRenderPass::draw
228
/// [`draw_indexed`]: TrackedRenderPass::draw_indexed
229
pub fn set_vertex_buffer(&mut self, slot_index: usize, buffer_slice: BufferSlice<'a>) {
230
if self.state.is_vertex_buffer_set(slot_index, &buffer_slice) {
231
#[cfg(feature = "detailed_trace")]
232
trace!(
233
"set vertex buffer {} (already set): {:?} (offset = {}, size = {})",
234
slot_index,
235
buffer_slice.id(),
236
buffer_slice.offset(),
237
buffer_slice.size(),
238
);
239
return;
240
}
241
#[cfg(feature = "detailed_trace")]
242
trace!(
243
"set vertex buffer {}: {:?} (offset = {}, size = {})",
244
slot_index,
245
buffer_slice.id(),
246
buffer_slice.offset(),
247
buffer_slice.size(),
248
);
249
250
self.pass
251
.set_vertex_buffer(slot_index as u32, *buffer_slice);
252
self.state.set_vertex_buffer(slot_index, buffer_slice);
253
}
254
255
/// Sets the active index buffer.
256
///
257
/// Subsequent calls to [`TrackedRenderPass::draw_indexed`] will use the buffer referenced by
258
/// `buffer_slice` as the source index buffer.
259
pub fn set_index_buffer(
260
&mut self,
261
buffer_slice: BufferSlice<'a>,
262
offset: u64,
263
index_format: IndexFormat,
264
) {
265
if self
266
.state
267
.is_index_buffer_set(buffer_slice.id(), offset, index_format)
268
{
269
#[cfg(feature = "detailed_trace")]
270
trace!(
271
"set index buffer (already set): {:?} ({})",
272
buffer_slice.id(),
273
offset
274
);
275
return;
276
}
277
#[cfg(feature = "detailed_trace")]
278
trace!("set index buffer: {:?} ({})", buffer_slice.id(), offset);
279
self.pass.set_index_buffer(*buffer_slice, index_format);
280
self.state
281
.set_index_buffer(buffer_slice.id(), offset, index_format);
282
}
283
284
/// Draws primitives from the active vertex buffer(s).
285
///
286
/// The active vertex buffer(s) can be set with [`TrackedRenderPass::set_vertex_buffer`].
287
pub fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
288
#[cfg(feature = "detailed_trace")]
289
trace!("draw: {:?} {:?}", vertices, instances);
290
self.pass.draw(vertices, instances);
291
}
292
293
/// Draws indexed primitives using the active index buffer and the active vertex buffer(s).
294
///
295
/// The active index buffer can be set with [`TrackedRenderPass::set_index_buffer`], while the
296
/// active vertex buffer(s) can be set with [`TrackedRenderPass::set_vertex_buffer`].
297
pub fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {
298
#[cfg(feature = "detailed_trace")]
299
trace!(
300
"draw indexed: {:?} {} {:?}",
301
indices,
302
base_vertex,
303
instances
304
);
305
self.pass.draw_indexed(indices, base_vertex, instances);
306
}
307
308
/// Draws primitives from the active vertex buffer(s) based on the contents of the
309
/// `indirect_buffer`.
310
///
311
/// The active vertex buffers can be set with [`TrackedRenderPass::set_vertex_buffer`].
312
///
313
/// The structure expected in `indirect_buffer` is the following:
314
///
315
/// ```
316
/// #[repr(C)]
317
/// struct DrawIndirect {
318
/// vertex_count: u32, // The number of vertices to draw.
319
/// instance_count: u32, // The number of instances to draw.
320
/// first_vertex: u32, // The Index of the first vertex to draw.
321
/// first_instance: u32, // The instance ID of the first instance to draw.
322
/// // has to be 0, unless [`Features::INDIRECT_FIRST_INSTANCE`] is enabled.
323
/// }
324
/// ```
325
pub fn draw_indirect(&mut self, indirect_buffer: &'a Buffer, indirect_offset: u64) {
326
#[cfg(feature = "detailed_trace")]
327
trace!("draw indirect: {:?} {}", indirect_buffer, indirect_offset);
328
self.pass.draw_indirect(indirect_buffer, indirect_offset);
329
}
330
331
/// Draws indexed primitives using the active index buffer and the active vertex buffers,
332
/// based on the contents of the `indirect_buffer`.
333
///
334
/// The active index buffer can be set with [`TrackedRenderPass::set_index_buffer`], while the
335
/// active vertex buffers can be set with [`TrackedRenderPass::set_vertex_buffer`].
336
///
337
/// The structure expected in `indirect_buffer` is the following:
338
///
339
/// ```
340
/// #[repr(C)]
341
/// struct DrawIndexedIndirect {
342
/// vertex_count: u32, // The number of vertices to draw.
343
/// instance_count: u32, // The number of instances to draw.
344
/// first_index: u32, // The base index within the index buffer.
345
/// vertex_offset: i32, // The value added to the vertex index before indexing into the vertex buffer.
346
/// first_instance: u32, // The instance ID of the first instance to draw.
347
/// // has to be 0, unless [`Features::INDIRECT_FIRST_INSTANCE`] is enabled.
348
/// }
349
/// ```
350
pub fn draw_indexed_indirect(&mut self, indirect_buffer: &'a Buffer, indirect_offset: u64) {
351
#[cfg(feature = "detailed_trace")]
352
trace!(
353
"draw indexed indirect: {:?} {}",
354
indirect_buffer,
355
indirect_offset
356
);
357
self.pass
358
.draw_indexed_indirect(indirect_buffer, indirect_offset);
359
}
360
361
/// Dispatches multiple draw calls from the active vertex buffer(s) based on the contents of the
362
/// `indirect_buffer`.`count` draw calls are issued.
363
///
364
/// The active vertex buffers can be set with [`TrackedRenderPass::set_vertex_buffer`].
365
///
366
/// `indirect_buffer` should contain `count` tightly packed elements of the following structure:
367
///
368
/// ```
369
/// #[repr(C)]
370
/// struct DrawIndirect {
371
/// vertex_count: u32, // The number of vertices to draw.
372
/// instance_count: u32, // The number of instances to draw.
373
/// first_vertex: u32, // The Index of the first vertex to draw.
374
/// first_instance: u32, // The instance ID of the first instance to draw.
375
/// // has to be 0, unless [`Features::INDIRECT_FIRST_INSTANCE`] is enabled.
376
/// }
377
/// ```
378
pub fn multi_draw_indirect(
379
&mut self,
380
indirect_buffer: &'a Buffer,
381
indirect_offset: u64,
382
count: u32,
383
) {
384
#[cfg(feature = "detailed_trace")]
385
trace!(
386
"multi draw indirect: {:?} {}, {}x",
387
indirect_buffer,
388
indirect_offset,
389
count
390
);
391
self.pass
392
.multi_draw_indirect(indirect_buffer, indirect_offset, count);
393
}
394
395
/// Dispatches multiple draw calls from the active vertex buffer(s) based on the contents of
396
/// the `indirect_buffer`.
397
/// The count buffer is read to determine how many draws to issue.
398
///
399
/// The indirect buffer must be long enough to account for `max_count` draws, however only
400
/// `count` elements will be read, where `count` is the value read from `count_buffer` capped
401
/// at `max_count`.
402
///
403
/// The active vertex buffers can be set with [`TrackedRenderPass::set_vertex_buffer`].
404
///
405
/// `indirect_buffer` should contain `count` tightly packed elements of the following structure:
406
///
407
/// ```
408
/// #[repr(C)]
409
/// struct DrawIndirect {
410
/// vertex_count: u32, // The number of vertices to draw.
411
/// instance_count: u32, // The number of instances to draw.
412
/// first_vertex: u32, // The Index of the first vertex to draw.
413
/// first_instance: u32, // The instance ID of the first instance to draw.
414
/// // has to be 0, unless [`Features::INDIRECT_FIRST_INSTANCE`] is enabled.
415
/// }
416
/// ```
417
pub fn multi_draw_indirect_count(
418
&mut self,
419
indirect_buffer: &'a Buffer,
420
indirect_offset: u64,
421
count_buffer: &'a Buffer,
422
count_offset: u64,
423
max_count: u32,
424
) {
425
#[cfg(feature = "detailed_trace")]
426
trace!(
427
"multi draw indirect count: {:?} {}, ({:?} {})x, max {}x",
428
indirect_buffer,
429
indirect_offset,
430
count_buffer,
431
count_offset,
432
max_count
433
);
434
self.pass.multi_draw_indirect_count(
435
indirect_buffer,
436
indirect_offset,
437
count_buffer,
438
count_offset,
439
max_count,
440
);
441
}
442
443
/// Dispatches multiple draw calls from the active index buffer and the active vertex buffers,
444
/// based on the contents of the `indirect_buffer`. `count` draw calls are issued.
445
///
446
/// The active index buffer can be set with [`TrackedRenderPass::set_index_buffer`], while the
447
/// active vertex buffers can be set with [`TrackedRenderPass::set_vertex_buffer`].
448
///
449
/// `indirect_buffer` should contain `count` tightly packed elements of the following structure:
450
///
451
/// ```
452
/// #[repr(C)]
453
/// struct DrawIndexedIndirect {
454
/// vertex_count: u32, // The number of vertices to draw.
455
/// instance_count: u32, // The number of instances to draw.
456
/// first_index: u32, // The base index within the index buffer.
457
/// vertex_offset: i32, // The value added to the vertex index before indexing into the vertex buffer.
458
/// first_instance: u32, // The instance ID of the first instance to draw.
459
/// // has to be 0, unless [`Features::INDIRECT_FIRST_INSTANCE`] is enabled.
460
/// }
461
/// ```
462
pub fn multi_draw_indexed_indirect(
463
&mut self,
464
indirect_buffer: &'a Buffer,
465
indirect_offset: u64,
466
count: u32,
467
) {
468
#[cfg(feature = "detailed_trace")]
469
trace!(
470
"multi draw indexed indirect: {:?} {}, {}x",
471
indirect_buffer,
472
indirect_offset,
473
count
474
);
475
self.pass
476
.multi_draw_indexed_indirect(indirect_buffer, indirect_offset, count);
477
}
478
479
/// Dispatches multiple draw calls from the active index buffer and the active vertex buffers,
480
/// based on the contents of the `indirect_buffer`.
481
/// The count buffer is read to determine how many draws to issue.
482
///
483
/// The indirect buffer must be long enough to account for `max_count` draws, however only
484
/// `count` elements will be read, where `count` is the value read from `count_buffer` capped
485
/// at `max_count`.
486
///
487
/// The active index buffer can be set with [`TrackedRenderPass::set_index_buffer`], while the
488
/// active vertex buffers can be set with [`TrackedRenderPass::set_vertex_buffer`].
489
///
490
/// `indirect_buffer` should contain `count` tightly packed elements of the following structure:
491
///
492
/// ```
493
/// #[repr(C)]
494
/// struct DrawIndexedIndirect {
495
/// vertex_count: u32, // The number of vertices to draw.
496
/// instance_count: u32, // The number of instances to draw.
497
/// first_index: u32, // The base index within the index buffer.
498
/// vertex_offset: i32, // The value added to the vertex index before indexing into the vertex buffer.
499
/// first_instance: u32, // The instance ID of the first instance to draw.
500
/// // has to be 0, unless [`Features::INDIRECT_FIRST_INSTANCE`] is enabled.
501
/// }
502
/// ```
503
pub fn multi_draw_indexed_indirect_count(
504
&mut self,
505
indirect_buffer: &'a Buffer,
506
indirect_offset: u64,
507
count_buffer: &'a Buffer,
508
count_offset: u64,
509
max_count: u32,
510
) {
511
#[cfg(feature = "detailed_trace")]
512
trace!(
513
"multi draw indexed indirect count: {:?} {}, ({:?} {})x, max {}x",
514
indirect_buffer,
515
indirect_offset,
516
count_buffer,
517
count_offset,
518
max_count
519
);
520
self.pass.multi_draw_indexed_indirect_count(
521
indirect_buffer,
522
indirect_offset,
523
count_buffer,
524
count_offset,
525
max_count,
526
);
527
}
528
529
/// Sets the stencil reference.
530
///
531
/// Subsequent stencil tests will test against this value.
532
pub fn set_stencil_reference(&mut self, reference: u32) {
533
#[cfg(feature = "detailed_trace")]
534
trace!("set stencil reference: {}", reference);
535
self.pass.set_stencil_reference(reference);
536
}
537
538
/// Sets the scissor region.
539
///
540
/// Subsequent draw calls will discard any fragments that fall outside this region.
541
pub fn set_scissor_rect(&mut self, x: u32, y: u32, width: u32, height: u32) {
542
#[cfg(feature = "detailed_trace")]
543
trace!("set_scissor_rect: {} {} {} {}", x, y, width, height);
544
self.pass.set_scissor_rect(x, y, width, height);
545
}
546
547
/// Set push constant data.
548
///
549
/// `Features::PUSH_CONSTANTS` must be enabled on the device in order to call these functions.
550
pub fn set_push_constants(&mut self, stages: ShaderStages, offset: u32, data: &[u8]) {
551
#[cfg(feature = "detailed_trace")]
552
trace!(
553
"set push constants: {:?} offset: {} data.len: {}",
554
stages,
555
offset,
556
data.len()
557
);
558
self.pass.set_push_constants(stages, offset, data);
559
}
560
561
/// Set the rendering viewport.
562
///
563
/// Subsequent draw calls will be projected into that viewport.
564
pub fn set_viewport(
565
&mut self,
566
x: f32,
567
y: f32,
568
width: f32,
569
height: f32,
570
min_depth: f32,
571
max_depth: f32,
572
) {
573
#[cfg(feature = "detailed_trace")]
574
trace!(
575
"set viewport: {} {} {} {} {} {}",
576
x,
577
y,
578
width,
579
height,
580
min_depth,
581
max_depth
582
);
583
self.pass
584
.set_viewport(x, y, width, height, min_depth, max_depth);
585
}
586
587
/// Set the rendering viewport to the given camera [`Viewport`].
588
///
589
/// Subsequent draw calls will be projected into that viewport.
590
pub fn set_camera_viewport(&mut self, viewport: &Viewport) {
591
self.set_viewport(
592
viewport.physical_position.x as f32,
593
viewport.physical_position.y as f32,
594
viewport.physical_size.x as f32,
595
viewport.physical_size.y as f32,
596
viewport.depth.start,
597
viewport.depth.end,
598
);
599
}
600
601
/// Insert a single debug marker.
602
///
603
/// This is a GPU debugging feature. This has no effect on the rendering itself.
604
pub fn insert_debug_marker(&mut self, label: &str) {
605
#[cfg(feature = "detailed_trace")]
606
trace!("insert debug marker: {}", label);
607
self.pass.insert_debug_marker(label);
608
}
609
610
/// Start a new debug group.
611
///
612
/// Push a new debug group over the internal stack. Subsequent render commands and debug
613
/// markers are grouped into this new group, until [`pop_debug_group`] is called.
614
///
615
/// ```
616
/// # fn example(mut pass: bevy_render::render_phase::TrackedRenderPass<'static>) {
617
/// pass.push_debug_group("Render the car");
618
/// // [setup pipeline etc...]
619
/// pass.draw(0..64, 0..1);
620
/// pass.pop_debug_group();
621
/// # }
622
/// ```
623
///
624
/// Note that [`push_debug_group`] and [`pop_debug_group`] must always be called in pairs.
625
///
626
/// This is a GPU debugging feature. This has no effect on the rendering itself.
627
///
628
/// [`push_debug_group`]: TrackedRenderPass::push_debug_group
629
/// [`pop_debug_group`]: TrackedRenderPass::pop_debug_group
630
pub fn push_debug_group(&mut self, label: &str) {
631
#[cfg(feature = "detailed_trace")]
632
trace!("push_debug_group marker: {}", label);
633
self.pass.push_debug_group(label);
634
}
635
636
/// End the current debug group.
637
///
638
/// Subsequent render commands and debug markers are not grouped anymore in
639
/// this group, but in the previous one (if any) or the default top-level one
640
/// if the debug group was the last one on the stack.
641
///
642
/// Note that [`push_debug_group`] and [`pop_debug_group`] must always be called in pairs.
643
///
644
/// This is a GPU debugging feature. This has no effect on the rendering itself.
645
///
646
/// [`push_debug_group`]: TrackedRenderPass::push_debug_group
647
/// [`pop_debug_group`]: TrackedRenderPass::pop_debug_group
648
pub fn pop_debug_group(&mut self) {
649
#[cfg(feature = "detailed_trace")]
650
trace!("pop_debug_group");
651
self.pass.pop_debug_group();
652
}
653
654
/// Sets the blend color as used by some of the blending modes.
655
///
656
/// Subsequent blending tests will test against this value.
657
pub fn set_blend_constant(&mut self, color: LinearRgba) {
658
#[cfg(feature = "detailed_trace")]
659
trace!("set blend constant: {:?}", color);
660
self.pass.set_blend_constant(wgpu::Color::from(color));
661
}
662
}
663
664
impl WriteTimestamp for TrackedRenderPass<'_> {
665
fn write_timestamp(&mut self, query_set: &QuerySet, index: u32) {
666
self.pass.write_timestamp(query_set, index);
667
}
668
}
669
670
impl WritePipelineStatistics for TrackedRenderPass<'_> {
671
fn begin_pipeline_statistics_query(&mut self, query_set: &QuerySet, index: u32) {
672
self.pass.begin_pipeline_statistics_query(query_set, index);
673
}
674
675
fn end_pipeline_statistics_query(&mut self) {
676
self.pass.end_pipeline_statistics_query();
677
}
678
}
679
680
impl Pass for TrackedRenderPass<'_> {
681
const KIND: PassKind = PassKind::Render;
682
}
683
684