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