Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_pbr/src/meshlet/visibility_buffer_raster_node.rs
6600 views
1
use super::{
2
pipelines::MeshletPipelines,
3
resource_manager::{MeshletViewBindGroups, MeshletViewResources},
4
};
5
use crate::{
6
meshlet::resource_manager::ResourceManager, LightEntity, ShadowView, ViewLightEntities,
7
};
8
use bevy_color::LinearRgba;
9
use bevy_core_pipeline::prepass::PreviousViewUniformOffset;
10
use bevy_ecs::{
11
query::QueryState,
12
world::{FromWorld, World},
13
};
14
use bevy_math::UVec2;
15
use bevy_render::{
16
camera::ExtractedCamera,
17
diagnostic::RecordDiagnostics,
18
render_graph::{Node, NodeRunError, RenderGraphContext},
19
render_resource::*,
20
renderer::RenderContext,
21
view::{ViewDepthTexture, ViewUniformOffset},
22
};
23
24
/// Rasterize meshlets into a depth buffer, and optional visibility buffer + material depth buffer for shading passes.
25
pub struct MeshletVisibilityBufferRasterPassNode {
26
main_view_query: QueryState<(
27
&'static ExtractedCamera,
28
&'static ViewDepthTexture,
29
&'static ViewUniformOffset,
30
&'static PreviousViewUniformOffset,
31
&'static MeshletViewBindGroups,
32
&'static MeshletViewResources,
33
&'static ViewLightEntities,
34
)>,
35
view_light_query: QueryState<(
36
&'static ShadowView,
37
&'static LightEntity,
38
&'static ViewUniformOffset,
39
&'static PreviousViewUniformOffset,
40
&'static MeshletViewBindGroups,
41
&'static MeshletViewResources,
42
)>,
43
}
44
45
impl FromWorld for MeshletVisibilityBufferRasterPassNode {
46
fn from_world(world: &mut World) -> Self {
47
Self {
48
main_view_query: QueryState::new(world),
49
view_light_query: QueryState::new(world),
50
}
51
}
52
}
53
54
impl Node for MeshletVisibilityBufferRasterPassNode {
55
fn update(&mut self, world: &mut World) {
56
self.main_view_query.update_archetypes(world);
57
self.view_light_query.update_archetypes(world);
58
}
59
60
// TODO: Reuse compute/render passes between logical passes where possible, as they're expensive
61
fn run(
62
&self,
63
graph: &mut RenderGraphContext,
64
render_context: &mut RenderContext,
65
world: &World,
66
) -> Result<(), NodeRunError> {
67
let Ok((
68
camera,
69
view_depth,
70
view_offset,
71
previous_view_offset,
72
meshlet_view_bind_groups,
73
meshlet_view_resources,
74
lights,
75
)) = self.main_view_query.get_manual(world, graph.view_entity())
76
else {
77
return Ok(());
78
};
79
80
let Some((
81
clear_visibility_buffer_pipeline,
82
clear_visibility_buffer_shadow_view_pipeline,
83
first_instance_cull_pipeline,
84
second_instance_cull_pipeline,
85
first_bvh_cull_pipeline,
86
second_bvh_cull_pipeline,
87
first_meshlet_cull_pipeline,
88
second_meshlet_cull_pipeline,
89
downsample_depth_first_pipeline,
90
downsample_depth_second_pipeline,
91
downsample_depth_first_shadow_view_pipeline,
92
downsample_depth_second_shadow_view_pipeline,
93
visibility_buffer_software_raster_pipeline,
94
visibility_buffer_software_raster_shadow_view_pipeline,
95
visibility_buffer_hardware_raster_pipeline,
96
visibility_buffer_hardware_raster_shadow_view_pipeline,
97
visibility_buffer_hardware_raster_shadow_view_unclipped_pipeline,
98
resolve_depth_pipeline,
99
resolve_depth_shadow_view_pipeline,
100
resolve_material_depth_pipeline,
101
remap_1d_to_2d_dispatch_pipeline,
102
fill_counts_pipeline,
103
)) = MeshletPipelines::get(world)
104
else {
105
return Ok(());
106
};
107
108
let diagnostics = render_context.diagnostic_recorder();
109
110
render_context
111
.command_encoder()
112
.push_debug_group("meshlet_visibility_buffer_raster");
113
let time_span = diagnostics.time_span(
114
render_context.command_encoder(),
115
"meshlet_visibility_buffer_raster",
116
);
117
118
let resource_manager = world.get_resource::<ResourceManager>().unwrap();
119
render_context.command_encoder().clear_buffer(
120
&resource_manager.visibility_buffer_raster_cluster_prev_counts,
121
0,
122
None,
123
);
124
125
clear_visibility_buffer_pass(
126
render_context,
127
&meshlet_view_bind_groups.clear_visibility_buffer,
128
clear_visibility_buffer_pipeline,
129
meshlet_view_resources.view_size,
130
);
131
132
render_context
133
.command_encoder()
134
.push_debug_group("meshlet_first_pass");
135
first_cull(
136
render_context,
137
meshlet_view_bind_groups,
138
meshlet_view_resources,
139
view_offset,
140
previous_view_offset,
141
first_instance_cull_pipeline,
142
first_bvh_cull_pipeline,
143
first_meshlet_cull_pipeline,
144
remap_1d_to_2d_dispatch_pipeline,
145
);
146
raster_pass(
147
true,
148
render_context,
149
&meshlet_view_resources.visibility_buffer_software_raster_indirect_args,
150
&meshlet_view_resources.visibility_buffer_hardware_raster_indirect_args,
151
&meshlet_view_resources.dummy_render_target.default_view,
152
meshlet_view_bind_groups,
153
view_offset,
154
visibility_buffer_software_raster_pipeline,
155
visibility_buffer_hardware_raster_pipeline,
156
fill_counts_pipeline,
157
Some(camera),
158
meshlet_view_resources.rightmost_slot,
159
);
160
render_context.command_encoder().pop_debug_group();
161
162
meshlet_view_resources.depth_pyramid.downsample_depth(
163
"downsample_depth",
164
render_context,
165
meshlet_view_resources.view_size,
166
&meshlet_view_bind_groups.downsample_depth,
167
downsample_depth_first_pipeline,
168
downsample_depth_second_pipeline,
169
);
170
171
render_context
172
.command_encoder()
173
.push_debug_group("meshlet_second_pass");
174
second_cull(
175
render_context,
176
meshlet_view_bind_groups,
177
meshlet_view_resources,
178
view_offset,
179
previous_view_offset,
180
second_instance_cull_pipeline,
181
second_bvh_cull_pipeline,
182
second_meshlet_cull_pipeline,
183
remap_1d_to_2d_dispatch_pipeline,
184
);
185
raster_pass(
186
false,
187
render_context,
188
&meshlet_view_resources.visibility_buffer_software_raster_indirect_args,
189
&meshlet_view_resources.visibility_buffer_hardware_raster_indirect_args,
190
&meshlet_view_resources.dummy_render_target.default_view,
191
meshlet_view_bind_groups,
192
view_offset,
193
visibility_buffer_software_raster_pipeline,
194
visibility_buffer_hardware_raster_pipeline,
195
fill_counts_pipeline,
196
Some(camera),
197
meshlet_view_resources.rightmost_slot,
198
);
199
render_context.command_encoder().pop_debug_group();
200
201
resolve_depth(
202
render_context,
203
view_depth.get_attachment(StoreOp::Store),
204
meshlet_view_bind_groups,
205
resolve_depth_pipeline,
206
camera,
207
);
208
resolve_material_depth(
209
render_context,
210
meshlet_view_resources,
211
meshlet_view_bind_groups,
212
resolve_material_depth_pipeline,
213
camera,
214
);
215
meshlet_view_resources.depth_pyramid.downsample_depth(
216
"downsample_depth",
217
render_context,
218
meshlet_view_resources.view_size,
219
&meshlet_view_bind_groups.downsample_depth,
220
downsample_depth_first_pipeline,
221
downsample_depth_second_pipeline,
222
);
223
render_context.command_encoder().pop_debug_group();
224
225
for light_entity in &lights.lights {
226
let Ok((
227
shadow_view,
228
light_type,
229
view_offset,
230
previous_view_offset,
231
meshlet_view_bind_groups,
232
meshlet_view_resources,
233
)) = self.view_light_query.get_manual(world, *light_entity)
234
else {
235
continue;
236
};
237
238
let shadow_visibility_buffer_hardware_raster_pipeline =
239
if let LightEntity::Directional { .. } = light_type {
240
visibility_buffer_hardware_raster_shadow_view_unclipped_pipeline
241
} else {
242
visibility_buffer_hardware_raster_shadow_view_pipeline
243
};
244
245
render_context.command_encoder().push_debug_group(&format!(
246
"meshlet_visibility_buffer_raster: {}",
247
shadow_view.pass_name
248
));
249
let pass_span = diagnostics.time_span(
250
render_context.command_encoder(),
251
shadow_view.pass_name.clone(),
252
);
253
clear_visibility_buffer_pass(
254
render_context,
255
&meshlet_view_bind_groups.clear_visibility_buffer,
256
clear_visibility_buffer_shadow_view_pipeline,
257
meshlet_view_resources.view_size,
258
);
259
260
render_context
261
.command_encoder()
262
.push_debug_group("meshlet_first_pass");
263
first_cull(
264
render_context,
265
meshlet_view_bind_groups,
266
meshlet_view_resources,
267
view_offset,
268
previous_view_offset,
269
first_instance_cull_pipeline,
270
first_bvh_cull_pipeline,
271
first_meshlet_cull_pipeline,
272
remap_1d_to_2d_dispatch_pipeline,
273
);
274
raster_pass(
275
true,
276
render_context,
277
&meshlet_view_resources.visibility_buffer_software_raster_indirect_args,
278
&meshlet_view_resources.visibility_buffer_hardware_raster_indirect_args,
279
&meshlet_view_resources.dummy_render_target.default_view,
280
meshlet_view_bind_groups,
281
view_offset,
282
visibility_buffer_software_raster_shadow_view_pipeline,
283
shadow_visibility_buffer_hardware_raster_pipeline,
284
fill_counts_pipeline,
285
None,
286
meshlet_view_resources.rightmost_slot,
287
);
288
render_context.command_encoder().pop_debug_group();
289
290
meshlet_view_resources.depth_pyramid.downsample_depth(
291
"downsample_depth",
292
render_context,
293
meshlet_view_resources.view_size,
294
&meshlet_view_bind_groups.downsample_depth,
295
downsample_depth_first_shadow_view_pipeline,
296
downsample_depth_second_shadow_view_pipeline,
297
);
298
299
render_context
300
.command_encoder()
301
.push_debug_group("meshlet_second_pass");
302
second_cull(
303
render_context,
304
meshlet_view_bind_groups,
305
meshlet_view_resources,
306
view_offset,
307
previous_view_offset,
308
second_instance_cull_pipeline,
309
second_bvh_cull_pipeline,
310
second_meshlet_cull_pipeline,
311
remap_1d_to_2d_dispatch_pipeline,
312
);
313
raster_pass(
314
false,
315
render_context,
316
&meshlet_view_resources.visibility_buffer_software_raster_indirect_args,
317
&meshlet_view_resources.visibility_buffer_hardware_raster_indirect_args,
318
&meshlet_view_resources.dummy_render_target.default_view,
319
meshlet_view_bind_groups,
320
view_offset,
321
visibility_buffer_software_raster_shadow_view_pipeline,
322
shadow_visibility_buffer_hardware_raster_pipeline,
323
fill_counts_pipeline,
324
None,
325
meshlet_view_resources.rightmost_slot,
326
);
327
render_context.command_encoder().pop_debug_group();
328
329
resolve_depth(
330
render_context,
331
shadow_view.depth_attachment.get_attachment(StoreOp::Store),
332
meshlet_view_bind_groups,
333
resolve_depth_shadow_view_pipeline,
334
camera,
335
);
336
meshlet_view_resources.depth_pyramid.downsample_depth(
337
"downsample_depth",
338
render_context,
339
meshlet_view_resources.view_size,
340
&meshlet_view_bind_groups.downsample_depth,
341
downsample_depth_first_shadow_view_pipeline,
342
downsample_depth_second_shadow_view_pipeline,
343
);
344
render_context.command_encoder().pop_debug_group();
345
pass_span.end(render_context.command_encoder());
346
}
347
348
time_span.end(render_context.command_encoder());
349
350
Ok(())
351
}
352
}
353
354
// TODO: Replace this with vkCmdClearColorImage once wgpu supports it
355
fn clear_visibility_buffer_pass(
356
render_context: &mut RenderContext,
357
clear_visibility_buffer_bind_group: &BindGroup,
358
clear_visibility_buffer_pipeline: &ComputePipeline,
359
view_size: UVec2,
360
) {
361
let command_encoder = render_context.command_encoder();
362
let mut clear_visibility_buffer_pass =
363
command_encoder.begin_compute_pass(&ComputePassDescriptor {
364
label: Some("clear_visibility_buffer"),
365
timestamp_writes: None,
366
});
367
clear_visibility_buffer_pass.set_pipeline(clear_visibility_buffer_pipeline);
368
clear_visibility_buffer_pass.set_push_constants(0, bytemuck::bytes_of(&view_size));
369
clear_visibility_buffer_pass.set_bind_group(0, clear_visibility_buffer_bind_group, &[]);
370
clear_visibility_buffer_pass.dispatch_workgroups(
371
view_size.x.div_ceil(16),
372
view_size.y.div_ceil(16),
373
1,
374
);
375
}
376
377
fn first_cull(
378
render_context: &mut RenderContext,
379
meshlet_view_bind_groups: &MeshletViewBindGroups,
380
meshlet_view_resources: &MeshletViewResources,
381
view_offset: &ViewUniformOffset,
382
previous_view_offset: &PreviousViewUniformOffset,
383
first_instance_cull_pipeline: &ComputePipeline,
384
first_bvh_cull_pipeline: &ComputePipeline,
385
first_meshlet_cull_pipeline: &ComputePipeline,
386
remap_1d_to_2d_pipeline: Option<&ComputePipeline>,
387
) {
388
let workgroups = meshlet_view_resources.scene_instance_count.div_ceil(128);
389
cull_pass(
390
"meshlet_first_instance_cull",
391
render_context,
392
&meshlet_view_bind_groups.first_instance_cull,
393
view_offset,
394
previous_view_offset,
395
first_instance_cull_pipeline,
396
&[meshlet_view_resources.scene_instance_count],
397
)
398
.dispatch_workgroups(workgroups, 1, 1);
399
400
render_context
401
.command_encoder()
402
.push_debug_group("meshlet_first_bvh_cull");
403
let mut ping = true;
404
for _ in 0..meshlet_view_resources.max_bvh_depth {
405
cull_pass(
406
"meshlet_first_bvh_cull_dispatch",
407
render_context,
408
if ping {
409
&meshlet_view_bind_groups.first_bvh_cull_ping
410
} else {
411
&meshlet_view_bind_groups.first_bvh_cull_pong
412
},
413
view_offset,
414
previous_view_offset,
415
first_bvh_cull_pipeline,
416
&[ping as u32, meshlet_view_resources.rightmost_slot],
417
)
418
.dispatch_workgroups_indirect(
419
if ping {
420
&meshlet_view_resources.first_bvh_cull_dispatch_front
421
} else {
422
&meshlet_view_resources.first_bvh_cull_dispatch_back
423
},
424
0,
425
);
426
render_context.command_encoder().clear_buffer(
427
if ping {
428
&meshlet_view_resources.first_bvh_cull_count_front
429
} else {
430
&meshlet_view_resources.first_bvh_cull_count_back
431
},
432
0,
433
Some(4),
434
);
435
render_context.command_encoder().clear_buffer(
436
if ping {
437
&meshlet_view_resources.first_bvh_cull_dispatch_front
438
} else {
439
&meshlet_view_resources.first_bvh_cull_dispatch_back
440
},
441
0,
442
Some(4),
443
);
444
ping = !ping;
445
}
446
render_context.command_encoder().pop_debug_group();
447
448
let mut pass = cull_pass(
449
"meshlet_first_meshlet_cull",
450
render_context,
451
&meshlet_view_bind_groups.first_meshlet_cull,
452
view_offset,
453
previous_view_offset,
454
first_meshlet_cull_pipeline,
455
&[meshlet_view_resources.rightmost_slot],
456
);
457
pass.dispatch_workgroups_indirect(&meshlet_view_resources.front_meshlet_cull_dispatch, 0);
458
remap_1d_to_2d(
459
pass,
460
remap_1d_to_2d_pipeline,
461
meshlet_view_bind_groups.remap_1d_to_2d_dispatch.as_ref(),
462
);
463
}
464
465
fn second_cull(
466
render_context: &mut RenderContext,
467
meshlet_view_bind_groups: &MeshletViewBindGroups,
468
meshlet_view_resources: &MeshletViewResources,
469
view_offset: &ViewUniformOffset,
470
previous_view_offset: &PreviousViewUniformOffset,
471
second_instance_cull_pipeline: &ComputePipeline,
472
second_bvh_cull_pipeline: &ComputePipeline,
473
second_meshlet_cull_pipeline: &ComputePipeline,
474
remap_1d_to_2d_pipeline: Option<&ComputePipeline>,
475
) {
476
cull_pass(
477
"meshlet_second_instance_cull",
478
render_context,
479
&meshlet_view_bind_groups.second_instance_cull,
480
view_offset,
481
previous_view_offset,
482
second_instance_cull_pipeline,
483
&[meshlet_view_resources.scene_instance_count],
484
)
485
.dispatch_workgroups_indirect(&meshlet_view_resources.second_pass_dispatch, 0);
486
487
render_context
488
.command_encoder()
489
.push_debug_group("meshlet_second_bvh_cull");
490
let mut ping = true;
491
for _ in 0..meshlet_view_resources.max_bvh_depth {
492
cull_pass(
493
"meshlet_second_bvh_cull_dispatch",
494
render_context,
495
if ping {
496
&meshlet_view_bind_groups.second_bvh_cull_ping
497
} else {
498
&meshlet_view_bind_groups.second_bvh_cull_pong
499
},
500
view_offset,
501
previous_view_offset,
502
second_bvh_cull_pipeline,
503
&[ping as u32, meshlet_view_resources.rightmost_slot],
504
)
505
.dispatch_workgroups_indirect(
506
if ping {
507
&meshlet_view_resources.second_bvh_cull_dispatch_front
508
} else {
509
&meshlet_view_resources.second_bvh_cull_dispatch_back
510
},
511
0,
512
);
513
ping = !ping;
514
}
515
render_context.command_encoder().pop_debug_group();
516
517
let mut pass = cull_pass(
518
"meshlet_second_meshlet_cull",
519
render_context,
520
&meshlet_view_bind_groups.second_meshlet_cull,
521
view_offset,
522
previous_view_offset,
523
second_meshlet_cull_pipeline,
524
&[meshlet_view_resources.rightmost_slot],
525
);
526
pass.dispatch_workgroups_indirect(&meshlet_view_resources.back_meshlet_cull_dispatch, 0);
527
remap_1d_to_2d(
528
pass,
529
remap_1d_to_2d_pipeline,
530
meshlet_view_bind_groups.remap_1d_to_2d_dispatch.as_ref(),
531
);
532
}
533
534
fn cull_pass<'a>(
535
label: &'static str,
536
render_context: &'a mut RenderContext,
537
bind_group: &'a BindGroup,
538
view_offset: &'a ViewUniformOffset,
539
previous_view_offset: &'a PreviousViewUniformOffset,
540
pipeline: &'a ComputePipeline,
541
push_constants: &[u32],
542
) -> ComputePass<'a> {
543
let command_encoder = render_context.command_encoder();
544
let mut pass = command_encoder.begin_compute_pass(&ComputePassDescriptor {
545
label: Some(label),
546
timestamp_writes: None,
547
});
548
pass.set_pipeline(pipeline);
549
pass.set_bind_group(
550
0,
551
bind_group,
552
&[view_offset.offset, previous_view_offset.offset],
553
);
554
pass.set_push_constants(0, bytemuck::cast_slice(push_constants));
555
pass
556
}
557
558
fn remap_1d_to_2d(
559
mut pass: ComputePass,
560
pipeline: Option<&ComputePipeline>,
561
bind_group: Option<&BindGroup>,
562
) {
563
if let (Some(pipeline), Some(bind_group)) = (pipeline, bind_group) {
564
pass.set_pipeline(pipeline);
565
pass.set_bind_group(0, bind_group, &[]);
566
pass.dispatch_workgroups(1, 1, 1);
567
}
568
}
569
570
fn raster_pass(
571
first_pass: bool,
572
render_context: &mut RenderContext,
573
visibility_buffer_software_raster_indirect_args: &Buffer,
574
visibility_buffer_hardware_raster_indirect_args: &Buffer,
575
dummy_render_target: &TextureView,
576
meshlet_view_bind_groups: &MeshletViewBindGroups,
577
view_offset: &ViewUniformOffset,
578
visibility_buffer_software_raster_pipeline: &ComputePipeline,
579
visibility_buffer_hardware_raster_pipeline: &RenderPipeline,
580
fill_counts_pipeline: &ComputePipeline,
581
camera: Option<&ExtractedCamera>,
582
raster_cluster_rightmost_slot: u32,
583
) {
584
let mut software_pass =
585
render_context
586
.command_encoder()
587
.begin_compute_pass(&ComputePassDescriptor {
588
label: Some(if first_pass {
589
"raster_software_first"
590
} else {
591
"raster_software_second"
592
}),
593
timestamp_writes: None,
594
});
595
software_pass.set_pipeline(visibility_buffer_software_raster_pipeline);
596
software_pass.set_bind_group(
597
0,
598
&meshlet_view_bind_groups.visibility_buffer_raster,
599
&[view_offset.offset],
600
);
601
software_pass.dispatch_workgroups_indirect(visibility_buffer_software_raster_indirect_args, 0);
602
drop(software_pass);
603
604
let mut hardware_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {
605
label: Some(if first_pass {
606
"raster_hardware_first"
607
} else {
608
"raster_hardware_second"
609
}),
610
color_attachments: &[Some(RenderPassColorAttachment {
611
view: dummy_render_target,
612
depth_slice: None,
613
resolve_target: None,
614
ops: Operations {
615
load: LoadOp::Clear(LinearRgba::BLACK.into()),
616
store: StoreOp::Discard,
617
},
618
})],
619
depth_stencil_attachment: None,
620
timestamp_writes: None,
621
occlusion_query_set: None,
622
});
623
if let Some(viewport) = camera.and_then(|camera| camera.viewport.as_ref()) {
624
hardware_pass.set_camera_viewport(viewport);
625
}
626
hardware_pass.set_render_pipeline(visibility_buffer_hardware_raster_pipeline);
627
hardware_pass.set_push_constants(
628
ShaderStages::VERTEX,
629
0,
630
&raster_cluster_rightmost_slot.to_le_bytes(),
631
);
632
hardware_pass.set_bind_group(
633
0,
634
&meshlet_view_bind_groups.visibility_buffer_raster,
635
&[view_offset.offset],
636
);
637
hardware_pass.draw_indirect(visibility_buffer_hardware_raster_indirect_args, 0);
638
drop(hardware_pass);
639
640
let mut fill_counts_pass =
641
render_context
642
.command_encoder()
643
.begin_compute_pass(&ComputePassDescriptor {
644
label: Some("fill_counts"),
645
timestamp_writes: None,
646
});
647
fill_counts_pass.set_pipeline(fill_counts_pipeline);
648
fill_counts_pass.set_bind_group(0, &meshlet_view_bind_groups.fill_counts, &[]);
649
fill_counts_pass.dispatch_workgroups(1, 1, 1);
650
}
651
652
fn resolve_depth(
653
render_context: &mut RenderContext,
654
depth_stencil_attachment: RenderPassDepthStencilAttachment,
655
meshlet_view_bind_groups: &MeshletViewBindGroups,
656
resolve_depth_pipeline: &RenderPipeline,
657
camera: &ExtractedCamera,
658
) {
659
let mut resolve_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {
660
label: Some("resolve_depth"),
661
color_attachments: &[],
662
depth_stencil_attachment: Some(depth_stencil_attachment),
663
timestamp_writes: None,
664
occlusion_query_set: None,
665
});
666
if let Some(viewport) = &camera.viewport {
667
resolve_pass.set_camera_viewport(viewport);
668
}
669
resolve_pass.set_render_pipeline(resolve_depth_pipeline);
670
resolve_pass.set_bind_group(0, &meshlet_view_bind_groups.resolve_depth, &[]);
671
resolve_pass.draw(0..3, 0..1);
672
}
673
674
fn resolve_material_depth(
675
render_context: &mut RenderContext,
676
meshlet_view_resources: &MeshletViewResources,
677
meshlet_view_bind_groups: &MeshletViewBindGroups,
678
resolve_material_depth_pipeline: &RenderPipeline,
679
camera: &ExtractedCamera,
680
) {
681
if let (Some(material_depth), Some(resolve_material_depth_bind_group)) = (
682
meshlet_view_resources.material_depth.as_ref(),
683
meshlet_view_bind_groups.resolve_material_depth.as_ref(),
684
) {
685
let mut resolve_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {
686
label: Some("resolve_material_depth"),
687
color_attachments: &[],
688
depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {
689
view: &material_depth.default_view,
690
depth_ops: Some(Operations {
691
load: LoadOp::Clear(0.0),
692
store: StoreOp::Store,
693
}),
694
stencil_ops: None,
695
}),
696
timestamp_writes: None,
697
occlusion_query_set: None,
698
});
699
if let Some(viewport) = &camera.viewport {
700
resolve_pass.set_camera_viewport(viewport);
701
}
702
resolve_pass.set_render_pipeline(resolve_material_depth_pipeline);
703
resolve_pass.set_bind_group(0, resolve_material_depth_bind_group, &[]);
704
resolve_pass.draw(0..3, 0..1);
705
}
706
}
707
708