pub struct TrackedRenderPass<'a> { /* private fields */ }bevy_render only.Expand description
A RenderPass, which tracks the current pipeline state to skip redundant operations.
It is used to set the current RenderPipeline, BindGroups and Buffers.
After all requirements are specified, draw calls can be issued.
Implementations§
Source§impl<'a> TrackedRenderPass<'a>
impl<'a> TrackedRenderPass<'a>
Sourcepub fn new(device: &RenderDevice, pass: RenderPass<'a>) -> TrackedRenderPass<'a>
pub fn new(device: &RenderDevice, pass: RenderPass<'a>) -> TrackedRenderPass<'a>
Tracks the supplied render pass.
Sourcepub fn wgpu_pass(&mut self) -> &mut RenderPass<'a>
pub fn wgpu_pass(&mut self) -> &mut RenderPass<'a>
Returns the wgpu RenderPass.
Function invalidates internal tracking state, some redundant pipeline operations may not be skipped.
Sourcepub fn set_render_pipeline(&mut self, pipeline: &'a RenderPipeline)
pub fn set_render_pipeline(&mut self, pipeline: &'a RenderPipeline)
Sets the active RenderPipeline.
Subsequent draw calls will exhibit the behavior defined by the pipeline.
Examples found in repository?
202fn draw_mesh_shader_cubes(
203 mut views: Query<(
204 &ExtractedCamera,
205 &ExtractedView,
206 &ViewTarget,
207 &ViewDepthStencilTexture,
208 &ViewUniformOffset,
209 Option<&MainPassResolutionOverride>,
210 )>,
211 mut render_context: RenderContext,
212 data: Res<MyMeshShaderDrawNode>,
213 view_uniforms: Res<ViewUniforms>,
214 globals: Res<GlobalsBuffer>,
215 pipeline_cache: Res<PipelineCache>,
216) {
217 let Some(mesh_pipeline) = pipeline_cache.get_render_pipeline(data.mesh_pipeline) else {
218 return;
219 };
220
221 for (camera, _, target, depth, view_uniform_offset, resolution_override) in &mut views {
222 let Some(view_binding) = view_uniforms.uniforms.binding() else {
223 return;
224 };
225 let Some(globals_binding) = globals.buffer.binding() else {
226 return;
227 };
228 let bind_group = render_context.render_device().create_bind_group(
229 "custom_task_mesh_bind_group",
230 &pipeline_cache.get_bind_group_layout(&data.layout),
231 &BindGroupEntries::sequential((globals_binding, view_binding)),
232 );
233
234 {
235 let mut pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {
236 label: Some("custom_mesh_shader_pass"),
237 // Write directly to the view target
238 color_attachments: &[Some(target.get_color_attachment())],
239 depth_stencil_attachment: Some(depth.get_attachment(StoreOp::Store)),
240 timestamp_writes: None,
241 occlusion_query_set: None,
242 multiview_mask: None,
243 });
244
245 pass.set_render_pipeline(mesh_pipeline);
246 pass.set_bind_group(0, &bind_group, &[view_uniform_offset.offset]);
247 if let Some(viewport) =
248 Viewport::from_viewport_and_override(camera.viewport.as_ref(), resolution_override)
249 {
250 pass.set_camera_viewport(&viewport);
251 }
252
253 // Since this MeshPipeline has a task shader, this call
254 // dispatches the task shader workgroup
255 pass.draw_mesh_tasks(1, 1, 1);
256 }
257 }
258}More examples
229fn raymarch_gbuffer_pass(
230 view: ViewQuery<(
231 &ViewUniformOffset,
232 &ViewDepthStencilTexture,
233 &ViewPrepassTextures,
234 )>,
235 pipeline: Option<Res<RaymarchGBufferPipeline>>,
236 pipeline_cache: Res<PipelineCache>,
237 view_uniforms: Res<ViewUniforms>,
238 globals: Res<GlobalsBuffer>,
239 mut ctx: RenderContext,
240) {
241 let Some(pipeline) = pipeline else {
242 return;
243 };
244 let Some(render_pipeline) = pipeline_cache.get_render_pipeline(pipeline.pipeline_id) else {
245 return;
246 };
247
248 let (view_uniform_offset, view_depth, view_prepass_textures) = view.into_inner();
249
250 let (Some(deferred), Some(lighting_pass_id)) = (
251 &view_prepass_textures.deferred,
252 &view_prepass_textures.deferred_lighting_pass_id,
253 ) else {
254 return;
255 };
256
257 let Some(bind_group) = raymarch_bind_group(
258 &ctx,
259 &pipeline_cache,
260 &pipeline.layout,
261 &view_uniforms,
262 &globals,
263 ) else {
264 return;
265 };
266
267 {
268 // We load rather than clear because we only want to overwrite the pixels which the deferred mesh
269 // prepass didn't write
270 let mut pass = ctx.begin_tracked_render_pass(RenderPassDescriptor {
271 label: Some("raymarch_gbuffer_pass"),
272 color_attachments: &[
273 Some(deferred.get_attachment()),
274 Some(lighting_pass_id.get_attachment()),
275 ],
276 depth_stencil_attachment: Some(view_depth.get_attachment(StoreOp::Store)),
277 timestamp_writes: None,
278 occlusion_query_set: None,
279 multiview_mask: None,
280 });
281
282 pass.set_render_pipeline(render_pipeline);
283 pass.set_bind_group(0, &bind_group, &[view_uniform_offset.offset]);
284 pass.draw(0..3, 0..1);
285 }
286
287 // The deferred lighting pass reconstructs world position from the prepass depth
288 // texture, not the depth attachment we just wrote, so we have to do a copy.
289 if let Some(prepass_depth) = &view_prepass_textures.depth {
290 ctx.command_encoder().copy_texture_to_texture(
291 view_depth.texture().as_image_copy(),
292 prepass_depth.texture.texture.as_image_copy(),
293 view_prepass_textures.size,
294 );
295 }
296}
297
298fn raymarch_directional_shadow_pass(
299 view: ViewQuery<&ViewLightEntities>,
300 shadow_views: Query<(&ShadowView, &ViewUniformOffset)>,
301 pipeline: Option<Res<RaymarchShadowPipeline>>,
302 pipeline_cache: Res<PipelineCache>,
303 view_uniforms: Res<ViewUniforms>,
304 globals: Res<GlobalsBuffer>,
305 mut ctx: RenderContext,
306) {
307 let Some(pipeline) = pipeline else {
308 return;
309 };
310 let Some(render_pipeline) = pipeline_cache.get_render_pipeline(pipeline.pipeline_id) else {
311 return;
312 };
313
314 let view_lights = view.into_inner();
315 for light_entity in view_lights.lights.iter().copied() {
316 let Ok((shadow_view, view_uniform_offset)) = shadow_views.get(light_entity) else {
317 continue;
318 };
319 draw_raymarch_shadow(
320 &mut ctx,
321 &pipeline_cache,
322 &pipeline.layout,
323 &view_uniforms,
324 &globals,
325 render_pipeline,
326 shadow_view,
327 view_uniform_offset,
328 );
329 }
330}
331
332fn raymarch_shared_shadow_pass(
333 view: ViewQuery<(&ShadowView, &ViewUniformOffset)>,
334 pipeline: Option<Res<RaymarchShadowPipeline>>,
335 pipeline_cache: Res<PipelineCache>,
336 view_uniforms: Res<ViewUniforms>,
337 globals: Res<GlobalsBuffer>,
338 mut ctx: RenderContext,
339) {
340 let Some(pipeline) = pipeline else {
341 return;
342 };
343 let Some(render_pipeline) = pipeline_cache.get_render_pipeline(pipeline.pipeline_id) else {
344 return;
345 };
346
347 let (shadow_view, view_uniform_offset) = view.into_inner();
348 draw_raymarch_shadow(
349 &mut ctx,
350 &pipeline_cache,
351 &pipeline.layout,
352 &view_uniforms,
353 &globals,
354 render_pipeline,
355 shadow_view,
356 view_uniform_offset,
357 );
358}
359
360fn draw_raymarch_shadow(
361 ctx: &mut RenderContext,
362 pipeline_cache: &PipelineCache,
363 layout: &BindGroupLayoutDescriptor,
364 view_uniforms: &ViewUniforms,
365 globals: &GlobalsBuffer,
366 render_pipeline: &RenderPipeline,
367 shadow_view: &ShadowView,
368 view_uniform_offset: &ViewUniformOffset,
369) {
370 let Some(bind_group) = raymarch_bind_group(ctx, pipeline_cache, layout, view_uniforms, globals)
371 else {
372 return;
373 };
374
375 let mut pass = ctx.begin_tracked_render_pass(RenderPassDescriptor {
376 label: Some("raymarch_shadow_pass"),
377 color_attachments: &[],
378 depth_stencil_attachment: Some(shadow_view.depth_attachment.get_attachment(StoreOp::Store)),
379 timestamp_writes: None,
380 occlusion_query_set: None,
381 multiview_mask: None,
382 });
383
384 pass.set_render_pipeline(render_pipeline);
385 pass.set_bind_group(0, &bind_group, &[view_uniform_offset.offset]);
386 pass.draw(0..3, 0..1);
387}Sourcepub fn set_bind_group(
&mut self,
index: usize,
bind_group: &'a BindGroup,
dynamic_uniform_indices: &[u32],
)
pub fn set_bind_group( &mut self, index: usize, bind_group: &'a BindGroup, dynamic_uniform_indices: &[u32], )
Sets the active bind group for a given bind group index. The bind group layout
in the active pipeline when any draw() function is called must match the layout of
this bind group.
If the bind group have dynamic offsets, provide them in binding order.
These offsets have to be aligned to WgpuLimits::min_uniform_buffer_offset_alignment
or WgpuLimits::min_storage_buffer_offset_alignment appropriately.
Examples found in repository?
720 fn render<'w>(
721 item: &P,
722 _view: (),
723 _item_query: Option<()>,
724 (mesh2d_bind_group, render_mesh2d_instances, mesh_allocator,metadata_fallback_buffer): SystemParamItem<
725 'w,
726 '_,
727 Self::Param,
728 >,
729 pass: &mut TrackedRenderPass<'w>,
730 ) -> RenderCommandResult {
731 let render_mesh2d_instances = render_mesh2d_instances.into_inner();
732 let mesh_allocator = mesh_allocator.into_inner();
733 let mesh2d_bind_group = mesh2d_bind_group.into_inner();
734
735 let Some(RenderMesh2dInstance { mesh_asset_id, .. }) =
736 render_mesh2d_instances.get(&item.main_entity())
737 else {
738 return RenderCommandResult::Skip;
739 };
740 let metadata_slab_id = mesh_allocator
741 .key_to_slab
742 .get(&bevy_render::mesh::allocator::MeshAllocationKey::new(
743 *mesh_asset_id,
744 bevy_render::mesh::allocator::ElementClass::Metadata,
745 ))
746 .cloned()
747 .unwrap_or(metadata_fallback_buffer.slab_id);
748 let Some(bind_group) = &mesh2d_bind_group.value.get(&metadata_slab_id) else {
749 return RenderCommandResult::Failure(
750 "The mesh2d bind group wasn't set in the render phase.",
751 );
752 };
753
754 let mut dynamic_offsets: [u32; 1] = Default::default();
755 let mut offset_count = 0;
756 if let PhaseItemExtraIndex::DynamicOffset(dynamic_offset) = item.extra_index() {
757 dynamic_offsets[offset_count] = dynamic_offset;
758 offset_count += 1;
759 }
760 pass.set_bind_group(I, bind_group, &dynamic_offsets[..offset_count]);
761 RenderCommandResult::Success
762 }More examples
202fn draw_mesh_shader_cubes(
203 mut views: Query<(
204 &ExtractedCamera,
205 &ExtractedView,
206 &ViewTarget,
207 &ViewDepthStencilTexture,
208 &ViewUniformOffset,
209 Option<&MainPassResolutionOverride>,
210 )>,
211 mut render_context: RenderContext,
212 data: Res<MyMeshShaderDrawNode>,
213 view_uniforms: Res<ViewUniforms>,
214 globals: Res<GlobalsBuffer>,
215 pipeline_cache: Res<PipelineCache>,
216) {
217 let Some(mesh_pipeline) = pipeline_cache.get_render_pipeline(data.mesh_pipeline) else {
218 return;
219 };
220
221 for (camera, _, target, depth, view_uniform_offset, resolution_override) in &mut views {
222 let Some(view_binding) = view_uniforms.uniforms.binding() else {
223 return;
224 };
225 let Some(globals_binding) = globals.buffer.binding() else {
226 return;
227 };
228 let bind_group = render_context.render_device().create_bind_group(
229 "custom_task_mesh_bind_group",
230 &pipeline_cache.get_bind_group_layout(&data.layout),
231 &BindGroupEntries::sequential((globals_binding, view_binding)),
232 );
233
234 {
235 let mut pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {
236 label: Some("custom_mesh_shader_pass"),
237 // Write directly to the view target
238 color_attachments: &[Some(target.get_color_attachment())],
239 depth_stencil_attachment: Some(depth.get_attachment(StoreOp::Store)),
240 timestamp_writes: None,
241 occlusion_query_set: None,
242 multiview_mask: None,
243 });
244
245 pass.set_render_pipeline(mesh_pipeline);
246 pass.set_bind_group(0, &bind_group, &[view_uniform_offset.offset]);
247 if let Some(viewport) =
248 Viewport::from_viewport_and_override(camera.viewport.as_ref(), resolution_override)
249 {
250 pass.set_camera_viewport(&viewport);
251 }
252
253 // Since this MeshPipeline has a task shader, this call
254 // dispatches the task shader workgroup
255 pass.draw_mesh_tasks(1, 1, 1);
256 }
257 }
258}229fn raymarch_gbuffer_pass(
230 view: ViewQuery<(
231 &ViewUniformOffset,
232 &ViewDepthStencilTexture,
233 &ViewPrepassTextures,
234 )>,
235 pipeline: Option<Res<RaymarchGBufferPipeline>>,
236 pipeline_cache: Res<PipelineCache>,
237 view_uniforms: Res<ViewUniforms>,
238 globals: Res<GlobalsBuffer>,
239 mut ctx: RenderContext,
240) {
241 let Some(pipeline) = pipeline else {
242 return;
243 };
244 let Some(render_pipeline) = pipeline_cache.get_render_pipeline(pipeline.pipeline_id) else {
245 return;
246 };
247
248 let (view_uniform_offset, view_depth, view_prepass_textures) = view.into_inner();
249
250 let (Some(deferred), Some(lighting_pass_id)) = (
251 &view_prepass_textures.deferred,
252 &view_prepass_textures.deferred_lighting_pass_id,
253 ) else {
254 return;
255 };
256
257 let Some(bind_group) = raymarch_bind_group(
258 &ctx,
259 &pipeline_cache,
260 &pipeline.layout,
261 &view_uniforms,
262 &globals,
263 ) else {
264 return;
265 };
266
267 {
268 // We load rather than clear because we only want to overwrite the pixels which the deferred mesh
269 // prepass didn't write
270 let mut pass = ctx.begin_tracked_render_pass(RenderPassDescriptor {
271 label: Some("raymarch_gbuffer_pass"),
272 color_attachments: &[
273 Some(deferred.get_attachment()),
274 Some(lighting_pass_id.get_attachment()),
275 ],
276 depth_stencil_attachment: Some(view_depth.get_attachment(StoreOp::Store)),
277 timestamp_writes: None,
278 occlusion_query_set: None,
279 multiview_mask: None,
280 });
281
282 pass.set_render_pipeline(render_pipeline);
283 pass.set_bind_group(0, &bind_group, &[view_uniform_offset.offset]);
284 pass.draw(0..3, 0..1);
285 }
286
287 // The deferred lighting pass reconstructs world position from the prepass depth
288 // texture, not the depth attachment we just wrote, so we have to do a copy.
289 if let Some(prepass_depth) = &view_prepass_textures.depth {
290 ctx.command_encoder().copy_texture_to_texture(
291 view_depth.texture().as_image_copy(),
292 prepass_depth.texture.texture.as_image_copy(),
293 view_prepass_textures.size,
294 );
295 }
296}
297
298fn raymarch_directional_shadow_pass(
299 view: ViewQuery<&ViewLightEntities>,
300 shadow_views: Query<(&ShadowView, &ViewUniformOffset)>,
301 pipeline: Option<Res<RaymarchShadowPipeline>>,
302 pipeline_cache: Res<PipelineCache>,
303 view_uniforms: Res<ViewUniforms>,
304 globals: Res<GlobalsBuffer>,
305 mut ctx: RenderContext,
306) {
307 let Some(pipeline) = pipeline else {
308 return;
309 };
310 let Some(render_pipeline) = pipeline_cache.get_render_pipeline(pipeline.pipeline_id) else {
311 return;
312 };
313
314 let view_lights = view.into_inner();
315 for light_entity in view_lights.lights.iter().copied() {
316 let Ok((shadow_view, view_uniform_offset)) = shadow_views.get(light_entity) else {
317 continue;
318 };
319 draw_raymarch_shadow(
320 &mut ctx,
321 &pipeline_cache,
322 &pipeline.layout,
323 &view_uniforms,
324 &globals,
325 render_pipeline,
326 shadow_view,
327 view_uniform_offset,
328 );
329 }
330}
331
332fn raymarch_shared_shadow_pass(
333 view: ViewQuery<(&ShadowView, &ViewUniformOffset)>,
334 pipeline: Option<Res<RaymarchShadowPipeline>>,
335 pipeline_cache: Res<PipelineCache>,
336 view_uniforms: Res<ViewUniforms>,
337 globals: Res<GlobalsBuffer>,
338 mut ctx: RenderContext,
339) {
340 let Some(pipeline) = pipeline else {
341 return;
342 };
343 let Some(render_pipeline) = pipeline_cache.get_render_pipeline(pipeline.pipeline_id) else {
344 return;
345 };
346
347 let (shadow_view, view_uniform_offset) = view.into_inner();
348 draw_raymarch_shadow(
349 &mut ctx,
350 &pipeline_cache,
351 &pipeline.layout,
352 &view_uniforms,
353 &globals,
354 render_pipeline,
355 shadow_view,
356 view_uniform_offset,
357 );
358}
359
360fn draw_raymarch_shadow(
361 ctx: &mut RenderContext,
362 pipeline_cache: &PipelineCache,
363 layout: &BindGroupLayoutDescriptor,
364 view_uniforms: &ViewUniforms,
365 globals: &GlobalsBuffer,
366 render_pipeline: &RenderPipeline,
367 shadow_view: &ShadowView,
368 view_uniform_offset: &ViewUniformOffset,
369) {
370 let Some(bind_group) = raymarch_bind_group(ctx, pipeline_cache, layout, view_uniforms, globals)
371 else {
372 return;
373 };
374
375 let mut pass = ctx.begin_tracked_render_pass(RenderPassDescriptor {
376 label: Some("raymarch_shadow_pass"),
377 color_attachments: &[],
378 depth_stencil_attachment: Some(shadow_view.depth_attachment.get_attachment(StoreOp::Store)),
379 timestamp_writes: None,
380 occlusion_query_set: None,
381 multiview_mask: None,
382 });
383
384 pass.set_render_pipeline(render_pipeline);
385 pass.set_bind_group(0, &bind_group, &[view_uniform_offset.offset]);
386 pass.draw(0..3, 0..1);
387}Sourcepub fn set_vertex_buffer(
&mut self,
slot_index: usize,
buffer_slice: BufferSlice<'a>,
)
pub fn set_vertex_buffer( &mut self, slot_index: usize, buffer_slice: BufferSlice<'a>, )
Assign a vertex buffer to a slot.
Subsequent calls to draw and draw_indexed on this
TrackedRenderPass will use buffer as one of the source vertex buffers.
The slot_index refers to the index of the matching descriptor in
VertexState::buffers.
Examples found in repository?
72 fn render<'w>(
73 _: &P,
74 _: ROQueryItem<'w, '_, Self::ViewQuery>,
75 _: Option<ROQueryItem<'w, '_, Self::ItemQuery>>,
76 custom_phase_item_buffers: SystemParamItem<'w, '_, Self::Param>,
77 pass: &mut TrackedRenderPass<'w>,
78 ) -> RenderCommandResult {
79 // Borrow check workaround.
80 let custom_phase_item_buffers = custom_phase_item_buffers.into_inner();
81
82 // Tell the GPU where the vertices are.
83 pass.set_vertex_buffer(
84 0,
85 custom_phase_item_buffers
86 .vertices
87 .buffer()
88 .unwrap()
89 .slice(..),
90 );
91
92 // Tell the GPU where the indices are.
93 pass.set_index_buffer(
94 custom_phase_item_buffers
95 .indices
96 .buffer()
97 .unwrap()
98 .slice(..),
99 IndexFormat::Uint32,
100 );
101
102 // Draw one triangle (3 vertices).
103 pass.draw_indexed(0..3, 0, 0..1);
104
105 RenderCommandResult::Success
106 }More examples
778 fn render<'w>(
779 item: &P,
780 _view: (),
781 _item_query: Option<()>,
782 (meshes, render_mesh2d_instances, mesh_allocator): SystemParamItem<'w, '_, Self::Param>,
783 pass: &mut TrackedRenderPass<'w>,
784 ) -> RenderCommandResult {
785 let meshes = meshes.into_inner();
786 let render_mesh2d_instances = render_mesh2d_instances.into_inner();
787 let mesh_allocator = mesh_allocator.into_inner();
788
789 let Some(RenderMesh2dInstance { mesh_asset_id, .. }) =
790 render_mesh2d_instances.get(&item.main_entity())
791 else {
792 return RenderCommandResult::Skip;
793 };
794 let Some(gpu_mesh) = meshes.get(*mesh_asset_id) else {
795 return RenderCommandResult::Skip;
796 };
797 let Some(vertex_buffer_slice) = mesh_allocator.mesh_vertex_slice(mesh_asset_id) else {
798 return RenderCommandResult::Skip;
799 };
800
801 pass.set_vertex_buffer(0, vertex_buffer_slice.buffer.slice(..));
802
803 let batch_range = item.batch_range();
804 match &gpu_mesh.buffer_info {
805 RenderMeshBufferInfo::Indexed {
806 index_format,
807 count,
808 } => {
809 let Some(index_buffer_slice) = mesh_allocator.mesh_index_slice(mesh_asset_id)
810 else {
811 return RenderCommandResult::Skip;
812 };
813
814 pass.set_index_buffer(index_buffer_slice.buffer.slice(..), *index_format);
815
816 pass.draw_indexed(
817 index_buffer_slice.range.start..(index_buffer_slice.range.start + count),
818 vertex_buffer_slice.range.start as i32,
819 batch_range.clone(),
820 );
821 }
822 RenderMeshBufferInfo::NonIndexed => {
823 pass.draw(vertex_buffer_slice.range, batch_range.clone());
824 }
825 }
826 RenderCommandResult::Success
827 }301 fn render<'w>(
302 item: &P,
303 _view: (),
304 instance_buffer: Option<&'w InstanceBuffer>,
305 (meshes, render_mesh_instances, mesh_allocator): SystemParamItem<'w, '_, Self::Param>,
306 pass: &mut TrackedRenderPass<'w>,
307 ) -> RenderCommandResult {
308 // A borrow check workaround.
309 let mesh_allocator = mesh_allocator.into_inner();
310
311 let Some(mesh_instance) = render_mesh_instances.render_mesh_queue_data(item.main_entity())
312 else {
313 return RenderCommandResult::Skip;
314 };
315 let Some(gpu_mesh) = meshes.into_inner().get(mesh_instance.mesh_asset_id()) else {
316 return RenderCommandResult::Skip;
317 };
318 let Some(instance_buffer) = instance_buffer else {
319 return RenderCommandResult::Skip;
320 };
321 let Some(vertex_buffer_slice) =
322 mesh_allocator.mesh_vertex_slice(&mesh_instance.mesh_asset_id())
323 else {
324 return RenderCommandResult::Skip;
325 };
326
327 pass.set_vertex_buffer(0, vertex_buffer_slice.buffer.slice(..));
328 pass.set_vertex_buffer(1, instance_buffer.buffer.slice(..));
329
330 match &gpu_mesh.buffer_info {
331 RenderMeshBufferInfo::Indexed {
332 index_format,
333 count,
334 } => {
335 let Some(index_buffer_slice) =
336 mesh_allocator.mesh_index_slice(&mesh_instance.mesh_asset_id())
337 else {
338 return RenderCommandResult::Skip;
339 };
340
341 pass.set_index_buffer(index_buffer_slice.buffer.slice(..), *index_format);
342 pass.draw_indexed(
343 index_buffer_slice.range.start..(index_buffer_slice.range.start + count),
344 vertex_buffer_slice.range.start as i32,
345 0..instance_buffer.length as u32,
346 );
347 }
348 RenderMeshBufferInfo::NonIndexed => {
349 pass.draw(vertex_buffer_slice.range, 0..instance_buffer.length as u32);
350 }
351 }
352 RenderCommandResult::Success
353 }Sourcepub fn set_index_buffer(
&mut self,
buffer_slice: BufferSlice<'a>,
index_format: IndexFormat,
)
pub fn set_index_buffer( &mut self, buffer_slice: BufferSlice<'a>, index_format: IndexFormat, )
Sets the active index buffer.
Subsequent calls to TrackedRenderPass::draw_indexed will use the buffer referenced by
buffer_slice as the source index buffer.
Examples found in repository?
72 fn render<'w>(
73 _: &P,
74 _: ROQueryItem<'w, '_, Self::ViewQuery>,
75 _: Option<ROQueryItem<'w, '_, Self::ItemQuery>>,
76 custom_phase_item_buffers: SystemParamItem<'w, '_, Self::Param>,
77 pass: &mut TrackedRenderPass<'w>,
78 ) -> RenderCommandResult {
79 // Borrow check workaround.
80 let custom_phase_item_buffers = custom_phase_item_buffers.into_inner();
81
82 // Tell the GPU where the vertices are.
83 pass.set_vertex_buffer(
84 0,
85 custom_phase_item_buffers
86 .vertices
87 .buffer()
88 .unwrap()
89 .slice(..),
90 );
91
92 // Tell the GPU where the indices are.
93 pass.set_index_buffer(
94 custom_phase_item_buffers
95 .indices
96 .buffer()
97 .unwrap()
98 .slice(..),
99 IndexFormat::Uint32,
100 );
101
102 // Draw one triangle (3 vertices).
103 pass.draw_indexed(0..3, 0, 0..1);
104
105 RenderCommandResult::Success
106 }More examples
778 fn render<'w>(
779 item: &P,
780 _view: (),
781 _item_query: Option<()>,
782 (meshes, render_mesh2d_instances, mesh_allocator): SystemParamItem<'w, '_, Self::Param>,
783 pass: &mut TrackedRenderPass<'w>,
784 ) -> RenderCommandResult {
785 let meshes = meshes.into_inner();
786 let render_mesh2d_instances = render_mesh2d_instances.into_inner();
787 let mesh_allocator = mesh_allocator.into_inner();
788
789 let Some(RenderMesh2dInstance { mesh_asset_id, .. }) =
790 render_mesh2d_instances.get(&item.main_entity())
791 else {
792 return RenderCommandResult::Skip;
793 };
794 let Some(gpu_mesh) = meshes.get(*mesh_asset_id) else {
795 return RenderCommandResult::Skip;
796 };
797 let Some(vertex_buffer_slice) = mesh_allocator.mesh_vertex_slice(mesh_asset_id) else {
798 return RenderCommandResult::Skip;
799 };
800
801 pass.set_vertex_buffer(0, vertex_buffer_slice.buffer.slice(..));
802
803 let batch_range = item.batch_range();
804 match &gpu_mesh.buffer_info {
805 RenderMeshBufferInfo::Indexed {
806 index_format,
807 count,
808 } => {
809 let Some(index_buffer_slice) = mesh_allocator.mesh_index_slice(mesh_asset_id)
810 else {
811 return RenderCommandResult::Skip;
812 };
813
814 pass.set_index_buffer(index_buffer_slice.buffer.slice(..), *index_format);
815
816 pass.draw_indexed(
817 index_buffer_slice.range.start..(index_buffer_slice.range.start + count),
818 vertex_buffer_slice.range.start as i32,
819 batch_range.clone(),
820 );
821 }
822 RenderMeshBufferInfo::NonIndexed => {
823 pass.draw(vertex_buffer_slice.range, batch_range.clone());
824 }
825 }
826 RenderCommandResult::Success
827 }301 fn render<'w>(
302 item: &P,
303 _view: (),
304 instance_buffer: Option<&'w InstanceBuffer>,
305 (meshes, render_mesh_instances, mesh_allocator): SystemParamItem<'w, '_, Self::Param>,
306 pass: &mut TrackedRenderPass<'w>,
307 ) -> RenderCommandResult {
308 // A borrow check workaround.
309 let mesh_allocator = mesh_allocator.into_inner();
310
311 let Some(mesh_instance) = render_mesh_instances.render_mesh_queue_data(item.main_entity())
312 else {
313 return RenderCommandResult::Skip;
314 };
315 let Some(gpu_mesh) = meshes.into_inner().get(mesh_instance.mesh_asset_id()) else {
316 return RenderCommandResult::Skip;
317 };
318 let Some(instance_buffer) = instance_buffer else {
319 return RenderCommandResult::Skip;
320 };
321 let Some(vertex_buffer_slice) =
322 mesh_allocator.mesh_vertex_slice(&mesh_instance.mesh_asset_id())
323 else {
324 return RenderCommandResult::Skip;
325 };
326
327 pass.set_vertex_buffer(0, vertex_buffer_slice.buffer.slice(..));
328 pass.set_vertex_buffer(1, instance_buffer.buffer.slice(..));
329
330 match &gpu_mesh.buffer_info {
331 RenderMeshBufferInfo::Indexed {
332 index_format,
333 count,
334 } => {
335 let Some(index_buffer_slice) =
336 mesh_allocator.mesh_index_slice(&mesh_instance.mesh_asset_id())
337 else {
338 return RenderCommandResult::Skip;
339 };
340
341 pass.set_index_buffer(index_buffer_slice.buffer.slice(..), *index_format);
342 pass.draw_indexed(
343 index_buffer_slice.range.start..(index_buffer_slice.range.start + count),
344 vertex_buffer_slice.range.start as i32,
345 0..instance_buffer.length as u32,
346 );
347 }
348 RenderMeshBufferInfo::NonIndexed => {
349 pass.draw(vertex_buffer_slice.range, 0..instance_buffer.length as u32);
350 }
351 }
352 RenderCommandResult::Success
353 }Sourcepub fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>)
pub fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>)
Draws primitives from the active vertex buffer(s).
The active vertex buffer(s) can be set with TrackedRenderPass::set_vertex_buffer.
Examples found in repository?
778 fn render<'w>(
779 item: &P,
780 _view: (),
781 _item_query: Option<()>,
782 (meshes, render_mesh2d_instances, mesh_allocator): SystemParamItem<'w, '_, Self::Param>,
783 pass: &mut TrackedRenderPass<'w>,
784 ) -> RenderCommandResult {
785 let meshes = meshes.into_inner();
786 let render_mesh2d_instances = render_mesh2d_instances.into_inner();
787 let mesh_allocator = mesh_allocator.into_inner();
788
789 let Some(RenderMesh2dInstance { mesh_asset_id, .. }) =
790 render_mesh2d_instances.get(&item.main_entity())
791 else {
792 return RenderCommandResult::Skip;
793 };
794 let Some(gpu_mesh) = meshes.get(*mesh_asset_id) else {
795 return RenderCommandResult::Skip;
796 };
797 let Some(vertex_buffer_slice) = mesh_allocator.mesh_vertex_slice(mesh_asset_id) else {
798 return RenderCommandResult::Skip;
799 };
800
801 pass.set_vertex_buffer(0, vertex_buffer_slice.buffer.slice(..));
802
803 let batch_range = item.batch_range();
804 match &gpu_mesh.buffer_info {
805 RenderMeshBufferInfo::Indexed {
806 index_format,
807 count,
808 } => {
809 let Some(index_buffer_slice) = mesh_allocator.mesh_index_slice(mesh_asset_id)
810 else {
811 return RenderCommandResult::Skip;
812 };
813
814 pass.set_index_buffer(index_buffer_slice.buffer.slice(..), *index_format);
815
816 pass.draw_indexed(
817 index_buffer_slice.range.start..(index_buffer_slice.range.start + count),
818 vertex_buffer_slice.range.start as i32,
819 batch_range.clone(),
820 );
821 }
822 RenderMeshBufferInfo::NonIndexed => {
823 pass.draw(vertex_buffer_slice.range, batch_range.clone());
824 }
825 }
826 RenderCommandResult::Success
827 }More examples
301 fn render<'w>(
302 item: &P,
303 _view: (),
304 instance_buffer: Option<&'w InstanceBuffer>,
305 (meshes, render_mesh_instances, mesh_allocator): SystemParamItem<'w, '_, Self::Param>,
306 pass: &mut TrackedRenderPass<'w>,
307 ) -> RenderCommandResult {
308 // A borrow check workaround.
309 let mesh_allocator = mesh_allocator.into_inner();
310
311 let Some(mesh_instance) = render_mesh_instances.render_mesh_queue_data(item.main_entity())
312 else {
313 return RenderCommandResult::Skip;
314 };
315 let Some(gpu_mesh) = meshes.into_inner().get(mesh_instance.mesh_asset_id()) else {
316 return RenderCommandResult::Skip;
317 };
318 let Some(instance_buffer) = instance_buffer else {
319 return RenderCommandResult::Skip;
320 };
321 let Some(vertex_buffer_slice) =
322 mesh_allocator.mesh_vertex_slice(&mesh_instance.mesh_asset_id())
323 else {
324 return RenderCommandResult::Skip;
325 };
326
327 pass.set_vertex_buffer(0, vertex_buffer_slice.buffer.slice(..));
328 pass.set_vertex_buffer(1, instance_buffer.buffer.slice(..));
329
330 match &gpu_mesh.buffer_info {
331 RenderMeshBufferInfo::Indexed {
332 index_format,
333 count,
334 } => {
335 let Some(index_buffer_slice) =
336 mesh_allocator.mesh_index_slice(&mesh_instance.mesh_asset_id())
337 else {
338 return RenderCommandResult::Skip;
339 };
340
341 pass.set_index_buffer(index_buffer_slice.buffer.slice(..), *index_format);
342 pass.draw_indexed(
343 index_buffer_slice.range.start..(index_buffer_slice.range.start + count),
344 vertex_buffer_slice.range.start as i32,
345 0..instance_buffer.length as u32,
346 );
347 }
348 RenderMeshBufferInfo::NonIndexed => {
349 pass.draw(vertex_buffer_slice.range, 0..instance_buffer.length as u32);
350 }
351 }
352 RenderCommandResult::Success
353 }229fn raymarch_gbuffer_pass(
230 view: ViewQuery<(
231 &ViewUniformOffset,
232 &ViewDepthStencilTexture,
233 &ViewPrepassTextures,
234 )>,
235 pipeline: Option<Res<RaymarchGBufferPipeline>>,
236 pipeline_cache: Res<PipelineCache>,
237 view_uniforms: Res<ViewUniforms>,
238 globals: Res<GlobalsBuffer>,
239 mut ctx: RenderContext,
240) {
241 let Some(pipeline) = pipeline else {
242 return;
243 };
244 let Some(render_pipeline) = pipeline_cache.get_render_pipeline(pipeline.pipeline_id) else {
245 return;
246 };
247
248 let (view_uniform_offset, view_depth, view_prepass_textures) = view.into_inner();
249
250 let (Some(deferred), Some(lighting_pass_id)) = (
251 &view_prepass_textures.deferred,
252 &view_prepass_textures.deferred_lighting_pass_id,
253 ) else {
254 return;
255 };
256
257 let Some(bind_group) = raymarch_bind_group(
258 &ctx,
259 &pipeline_cache,
260 &pipeline.layout,
261 &view_uniforms,
262 &globals,
263 ) else {
264 return;
265 };
266
267 {
268 // We load rather than clear because we only want to overwrite the pixels which the deferred mesh
269 // prepass didn't write
270 let mut pass = ctx.begin_tracked_render_pass(RenderPassDescriptor {
271 label: Some("raymarch_gbuffer_pass"),
272 color_attachments: &[
273 Some(deferred.get_attachment()),
274 Some(lighting_pass_id.get_attachment()),
275 ],
276 depth_stencil_attachment: Some(view_depth.get_attachment(StoreOp::Store)),
277 timestamp_writes: None,
278 occlusion_query_set: None,
279 multiview_mask: None,
280 });
281
282 pass.set_render_pipeline(render_pipeline);
283 pass.set_bind_group(0, &bind_group, &[view_uniform_offset.offset]);
284 pass.draw(0..3, 0..1);
285 }
286
287 // The deferred lighting pass reconstructs world position from the prepass depth
288 // texture, not the depth attachment we just wrote, so we have to do a copy.
289 if let Some(prepass_depth) = &view_prepass_textures.depth {
290 ctx.command_encoder().copy_texture_to_texture(
291 view_depth.texture().as_image_copy(),
292 prepass_depth.texture.texture.as_image_copy(),
293 view_prepass_textures.size,
294 );
295 }
296}
297
298fn raymarch_directional_shadow_pass(
299 view: ViewQuery<&ViewLightEntities>,
300 shadow_views: Query<(&ShadowView, &ViewUniformOffset)>,
301 pipeline: Option<Res<RaymarchShadowPipeline>>,
302 pipeline_cache: Res<PipelineCache>,
303 view_uniforms: Res<ViewUniforms>,
304 globals: Res<GlobalsBuffer>,
305 mut ctx: RenderContext,
306) {
307 let Some(pipeline) = pipeline else {
308 return;
309 };
310 let Some(render_pipeline) = pipeline_cache.get_render_pipeline(pipeline.pipeline_id) else {
311 return;
312 };
313
314 let view_lights = view.into_inner();
315 for light_entity in view_lights.lights.iter().copied() {
316 let Ok((shadow_view, view_uniform_offset)) = shadow_views.get(light_entity) else {
317 continue;
318 };
319 draw_raymarch_shadow(
320 &mut ctx,
321 &pipeline_cache,
322 &pipeline.layout,
323 &view_uniforms,
324 &globals,
325 render_pipeline,
326 shadow_view,
327 view_uniform_offset,
328 );
329 }
330}
331
332fn raymarch_shared_shadow_pass(
333 view: ViewQuery<(&ShadowView, &ViewUniformOffset)>,
334 pipeline: Option<Res<RaymarchShadowPipeline>>,
335 pipeline_cache: Res<PipelineCache>,
336 view_uniforms: Res<ViewUniforms>,
337 globals: Res<GlobalsBuffer>,
338 mut ctx: RenderContext,
339) {
340 let Some(pipeline) = pipeline else {
341 return;
342 };
343 let Some(render_pipeline) = pipeline_cache.get_render_pipeline(pipeline.pipeline_id) else {
344 return;
345 };
346
347 let (shadow_view, view_uniform_offset) = view.into_inner();
348 draw_raymarch_shadow(
349 &mut ctx,
350 &pipeline_cache,
351 &pipeline.layout,
352 &view_uniforms,
353 &globals,
354 render_pipeline,
355 shadow_view,
356 view_uniform_offset,
357 );
358}
359
360fn draw_raymarch_shadow(
361 ctx: &mut RenderContext,
362 pipeline_cache: &PipelineCache,
363 layout: &BindGroupLayoutDescriptor,
364 view_uniforms: &ViewUniforms,
365 globals: &GlobalsBuffer,
366 render_pipeline: &RenderPipeline,
367 shadow_view: &ShadowView,
368 view_uniform_offset: &ViewUniformOffset,
369) {
370 let Some(bind_group) = raymarch_bind_group(ctx, pipeline_cache, layout, view_uniforms, globals)
371 else {
372 return;
373 };
374
375 let mut pass = ctx.begin_tracked_render_pass(RenderPassDescriptor {
376 label: Some("raymarch_shadow_pass"),
377 color_attachments: &[],
378 depth_stencil_attachment: Some(shadow_view.depth_attachment.get_attachment(StoreOp::Store)),
379 timestamp_writes: None,
380 occlusion_query_set: None,
381 multiview_mask: None,
382 });
383
384 pass.set_render_pipeline(render_pipeline);
385 pass.set_bind_group(0, &bind_group, &[view_uniform_offset.offset]);
386 pass.draw(0..3, 0..1);
387}Sourcepub fn draw_mesh_tasks(
&mut self,
group_count_x: u32,
group_count_y: u32,
group_count_z: u32,
)
pub fn draw_mesh_tasks( &mut self, group_count_x: u32, group_count_y: u32, group_count_z: u32, )
Draws using a mesh pipeline.
Note that the current pipeline must be a mesh pipeline.
If the mesh pipeline has a task shader, this runs the task shader with every workgroup specified
If the mesh pipeline has no task shader, this runs the mesh shader with every workgroup specified
Examples found in repository?
202fn draw_mesh_shader_cubes(
203 mut views: Query<(
204 &ExtractedCamera,
205 &ExtractedView,
206 &ViewTarget,
207 &ViewDepthStencilTexture,
208 &ViewUniformOffset,
209 Option<&MainPassResolutionOverride>,
210 )>,
211 mut render_context: RenderContext,
212 data: Res<MyMeshShaderDrawNode>,
213 view_uniforms: Res<ViewUniforms>,
214 globals: Res<GlobalsBuffer>,
215 pipeline_cache: Res<PipelineCache>,
216) {
217 let Some(mesh_pipeline) = pipeline_cache.get_render_pipeline(data.mesh_pipeline) else {
218 return;
219 };
220
221 for (camera, _, target, depth, view_uniform_offset, resolution_override) in &mut views {
222 let Some(view_binding) = view_uniforms.uniforms.binding() else {
223 return;
224 };
225 let Some(globals_binding) = globals.buffer.binding() else {
226 return;
227 };
228 let bind_group = render_context.render_device().create_bind_group(
229 "custom_task_mesh_bind_group",
230 &pipeline_cache.get_bind_group_layout(&data.layout),
231 &BindGroupEntries::sequential((globals_binding, view_binding)),
232 );
233
234 {
235 let mut pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {
236 label: Some("custom_mesh_shader_pass"),
237 // Write directly to the view target
238 color_attachments: &[Some(target.get_color_attachment())],
239 depth_stencil_attachment: Some(depth.get_attachment(StoreOp::Store)),
240 timestamp_writes: None,
241 occlusion_query_set: None,
242 multiview_mask: None,
243 });
244
245 pass.set_render_pipeline(mesh_pipeline);
246 pass.set_bind_group(0, &bind_group, &[view_uniform_offset.offset]);
247 if let Some(viewport) =
248 Viewport::from_viewport_and_override(camera.viewport.as_ref(), resolution_override)
249 {
250 pass.set_camera_viewport(&viewport);
251 }
252
253 // Since this MeshPipeline has a task shader, this call
254 // dispatches the task shader workgroup
255 pass.draw_mesh_tasks(1, 1, 1);
256 }
257 }
258}Sourcepub fn draw_mesh_tasks_indirect(
&mut self,
indirect_buffer: &Buffer,
indirect_offset: u64,
)
pub fn draw_mesh_tasks_indirect( &mut self, indirect_buffer: &Buffer, indirect_offset: u64, )
Draws using a mesh pipeline, based on the contents of the indirect_buffer
This is like calling draw_mesh_tasks but the contents of the call are specified in the indirect_buffer
The structure expected in indirect_buffer is the following:
#[repr(C)]
pub struct DispatchIndirectArgs {
pub x: u32,
pub y: u32,
pub z: u32,
}Sourcepub fn multi_draw_mesh_tasks_indirect(
&mut self,
indirect_buffer: &'a Buffer,
indirect_offset: u64,
count: u32,
)
pub fn multi_draw_mesh_tasks_indirect( &mut self, indirect_buffer: &'a Buffer, indirect_offset: u64, count: u32, )
Dispatches multiple draw calls based on the contents of the indirect_buffer. count draw calls are issued.
The structure expected in indirect_buffer is the following:
#[repr(C)]
pub struct DispatchIndirectArgs {
pub x: u32,
pub y: u32,
pub z: u32,
}Sourcepub fn multi_draw_mesh_tasks_indirect_count(
&mut self,
indirect_buffer: &'a Buffer,
indirect_offset: u64,
count_buffer: &'a Buffer,
count_offset: u64,
max_count: u32,
)
pub fn multi_draw_mesh_tasks_indirect_count( &mut self, indirect_buffer: &'a Buffer, indirect_offset: u64, count_buffer: &'a Buffer, count_offset: u64, max_count: u32, )
Dispatches multiple draw calls based on the contents of the indirect_buffer. The count buffer is read to determine how many draws to issue.
The indirect buffer must be long enough to account for max_count draws, however only count draws will be read. If count is greater than max_count, max_count will be used.
The structure expected in indirect_buffer is the following:
#[repr(C)]
pub struct DispatchIndirectArgs {
pub x: u32,
pub y: u32,
pub z: u32,
}Sourcepub fn draw_indexed(
&mut self,
indices: Range<u32>,
base_vertex: i32,
instances: Range<u32>,
)
pub fn draw_indexed( &mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>, )
Draws indexed primitives using the active index buffer and the active vertex buffer(s).
The active index buffer can be set with TrackedRenderPass::set_index_buffer, while the
active vertex buffer(s) can be set with TrackedRenderPass::set_vertex_buffer.
Examples found in repository?
72 fn render<'w>(
73 _: &P,
74 _: ROQueryItem<'w, '_, Self::ViewQuery>,
75 _: Option<ROQueryItem<'w, '_, Self::ItemQuery>>,
76 custom_phase_item_buffers: SystemParamItem<'w, '_, Self::Param>,
77 pass: &mut TrackedRenderPass<'w>,
78 ) -> RenderCommandResult {
79 // Borrow check workaround.
80 let custom_phase_item_buffers = custom_phase_item_buffers.into_inner();
81
82 // Tell the GPU where the vertices are.
83 pass.set_vertex_buffer(
84 0,
85 custom_phase_item_buffers
86 .vertices
87 .buffer()
88 .unwrap()
89 .slice(..),
90 );
91
92 // Tell the GPU where the indices are.
93 pass.set_index_buffer(
94 custom_phase_item_buffers
95 .indices
96 .buffer()
97 .unwrap()
98 .slice(..),
99 IndexFormat::Uint32,
100 );
101
102 // Draw one triangle (3 vertices).
103 pass.draw_indexed(0..3, 0, 0..1);
104
105 RenderCommandResult::Success
106 }More examples
778 fn render<'w>(
779 item: &P,
780 _view: (),
781 _item_query: Option<()>,
782 (meshes, render_mesh2d_instances, mesh_allocator): SystemParamItem<'w, '_, Self::Param>,
783 pass: &mut TrackedRenderPass<'w>,
784 ) -> RenderCommandResult {
785 let meshes = meshes.into_inner();
786 let render_mesh2d_instances = render_mesh2d_instances.into_inner();
787 let mesh_allocator = mesh_allocator.into_inner();
788
789 let Some(RenderMesh2dInstance { mesh_asset_id, .. }) =
790 render_mesh2d_instances.get(&item.main_entity())
791 else {
792 return RenderCommandResult::Skip;
793 };
794 let Some(gpu_mesh) = meshes.get(*mesh_asset_id) else {
795 return RenderCommandResult::Skip;
796 };
797 let Some(vertex_buffer_slice) = mesh_allocator.mesh_vertex_slice(mesh_asset_id) else {
798 return RenderCommandResult::Skip;
799 };
800
801 pass.set_vertex_buffer(0, vertex_buffer_slice.buffer.slice(..));
802
803 let batch_range = item.batch_range();
804 match &gpu_mesh.buffer_info {
805 RenderMeshBufferInfo::Indexed {
806 index_format,
807 count,
808 } => {
809 let Some(index_buffer_slice) = mesh_allocator.mesh_index_slice(mesh_asset_id)
810 else {
811 return RenderCommandResult::Skip;
812 };
813
814 pass.set_index_buffer(index_buffer_slice.buffer.slice(..), *index_format);
815
816 pass.draw_indexed(
817 index_buffer_slice.range.start..(index_buffer_slice.range.start + count),
818 vertex_buffer_slice.range.start as i32,
819 batch_range.clone(),
820 );
821 }
822 RenderMeshBufferInfo::NonIndexed => {
823 pass.draw(vertex_buffer_slice.range, batch_range.clone());
824 }
825 }
826 RenderCommandResult::Success
827 }301 fn render<'w>(
302 item: &P,
303 _view: (),
304 instance_buffer: Option<&'w InstanceBuffer>,
305 (meshes, render_mesh_instances, mesh_allocator): SystemParamItem<'w, '_, Self::Param>,
306 pass: &mut TrackedRenderPass<'w>,
307 ) -> RenderCommandResult {
308 // A borrow check workaround.
309 let mesh_allocator = mesh_allocator.into_inner();
310
311 let Some(mesh_instance) = render_mesh_instances.render_mesh_queue_data(item.main_entity())
312 else {
313 return RenderCommandResult::Skip;
314 };
315 let Some(gpu_mesh) = meshes.into_inner().get(mesh_instance.mesh_asset_id()) else {
316 return RenderCommandResult::Skip;
317 };
318 let Some(instance_buffer) = instance_buffer else {
319 return RenderCommandResult::Skip;
320 };
321 let Some(vertex_buffer_slice) =
322 mesh_allocator.mesh_vertex_slice(&mesh_instance.mesh_asset_id())
323 else {
324 return RenderCommandResult::Skip;
325 };
326
327 pass.set_vertex_buffer(0, vertex_buffer_slice.buffer.slice(..));
328 pass.set_vertex_buffer(1, instance_buffer.buffer.slice(..));
329
330 match &gpu_mesh.buffer_info {
331 RenderMeshBufferInfo::Indexed {
332 index_format,
333 count,
334 } => {
335 let Some(index_buffer_slice) =
336 mesh_allocator.mesh_index_slice(&mesh_instance.mesh_asset_id())
337 else {
338 return RenderCommandResult::Skip;
339 };
340
341 pass.set_index_buffer(index_buffer_slice.buffer.slice(..), *index_format);
342 pass.draw_indexed(
343 index_buffer_slice.range.start..(index_buffer_slice.range.start + count),
344 vertex_buffer_slice.range.start as i32,
345 0..instance_buffer.length as u32,
346 );
347 }
348 RenderMeshBufferInfo::NonIndexed => {
349 pass.draw(vertex_buffer_slice.range, 0..instance_buffer.length as u32);
350 }
351 }
352 RenderCommandResult::Success
353 }Sourcepub fn draw_indirect(
&mut self,
indirect_buffer: &'a Buffer,
indirect_offset: u64,
)
pub fn draw_indirect( &mut self, indirect_buffer: &'a Buffer, indirect_offset: u64, )
Draws primitives from the active vertex buffer(s) based on the contents of the
indirect_buffer.
The active vertex buffers can be set with TrackedRenderPass::set_vertex_buffer.
The structure expected in indirect_buffer is the following:
#[repr(C)]
struct DrawIndirect {
vertex_count: u32, // The number of vertices to draw.
instance_count: u32, // The number of instances to draw.
first_vertex: u32, // The Index of the first vertex to draw.
first_instance: u32, // The instance ID of the first instance to draw.
// has to be 0, unless [`Features::INDIRECT_FIRST_INSTANCE`] is enabled.
}Sourcepub fn draw_indexed_indirect(
&mut self,
indirect_buffer: &'a Buffer,
indirect_offset: u64,
)
pub fn draw_indexed_indirect( &mut self, indirect_buffer: &'a Buffer, indirect_offset: u64, )
Draws indexed primitives using the active index buffer and the active vertex buffers,
based on the contents of the indirect_buffer.
The active index buffer can be set with TrackedRenderPass::set_index_buffer, while the
active vertex buffers can be set with TrackedRenderPass::set_vertex_buffer.
The structure expected in indirect_buffer is the following:
#[repr(C)]
struct DrawIndexedIndirect {
vertex_count: u32, // The number of vertices to draw.
instance_count: u32, // The number of instances to draw.
first_index: u32, // The base index within the index buffer.
vertex_offset: i32, // The value added to the vertex index before indexing into the vertex buffer.
first_instance: u32, // The instance ID of the first instance to draw.
// has to be 0, unless [`Features::INDIRECT_FIRST_INSTANCE`] is enabled.
}Sourcepub fn multi_draw_indirect(
&mut self,
indirect_buffer: &'a Buffer,
indirect_offset: u64,
count: u32,
)
pub fn multi_draw_indirect( &mut self, indirect_buffer: &'a Buffer, indirect_offset: u64, count: u32, )
Dispatches multiple draw calls from the active vertex buffer(s) based on the contents of the
indirect_buffer.count draw calls are issued.
The active vertex buffers can be set with TrackedRenderPass::set_vertex_buffer.
indirect_buffer should contain count tightly packed elements of the following structure:
#[repr(C)]
struct DrawIndirect {
vertex_count: u32, // The number of vertices to draw.
instance_count: u32, // The number of instances to draw.
first_vertex: u32, // The Index of the first vertex to draw.
first_instance: u32, // The instance ID of the first instance to draw.
// has to be 0, unless [`Features::INDIRECT_FIRST_INSTANCE`] is enabled.
}Sourcepub fn multi_draw_indirect_count(
&mut self,
indirect_buffer: &'a Buffer,
indirect_offset: u64,
count_buffer: &'a Buffer,
count_offset: u64,
max_count: u32,
)
pub fn multi_draw_indirect_count( &mut self, indirect_buffer: &'a Buffer, indirect_offset: u64, count_buffer: &'a Buffer, count_offset: u64, max_count: u32, )
Dispatches multiple draw calls from the active vertex buffer(s) based on the contents of
the indirect_buffer.
The count buffer is read to determine how many draws to issue.
The indirect buffer must be long enough to account for max_count draws, however only
count elements will be read, where count is the value read from count_buffer capped
at max_count.
The active vertex buffers can be set with TrackedRenderPass::set_vertex_buffer.
indirect_buffer should contain count tightly packed elements of the following structure:
#[repr(C)]
struct DrawIndirect {
vertex_count: u32, // The number of vertices to draw.
instance_count: u32, // The number of instances to draw.
first_vertex: u32, // The Index of the first vertex to draw.
first_instance: u32, // The instance ID of the first instance to draw.
// has to be 0, unless [`Features::INDIRECT_FIRST_INSTANCE`] is enabled.
}Sourcepub fn multi_draw_indexed_indirect(
&mut self,
indirect_buffer: &'a Buffer,
indirect_offset: u64,
count: u32,
)
pub fn multi_draw_indexed_indirect( &mut self, indirect_buffer: &'a Buffer, indirect_offset: u64, count: u32, )
Dispatches multiple draw calls from the active index buffer and the active vertex buffers,
based on the contents of the indirect_buffer. count draw calls are issued.
The active index buffer can be set with TrackedRenderPass::set_index_buffer, while the
active vertex buffers can be set with TrackedRenderPass::set_vertex_buffer.
indirect_buffer should contain count tightly packed elements of the following structure:
#[repr(C)]
struct DrawIndexedIndirect {
vertex_count: u32, // The number of vertices to draw.
instance_count: u32, // The number of instances to draw.
first_index: u32, // The base index within the index buffer.
vertex_offset: i32, // The value added to the vertex index before indexing into the vertex buffer.
first_instance: u32, // The instance ID of the first instance to draw.
// has to be 0, unless [`Features::INDIRECT_FIRST_INSTANCE`] is enabled.
}Sourcepub fn multi_draw_indexed_indirect_count(
&mut self,
indirect_buffer: &'a Buffer,
indirect_offset: u64,
count_buffer: &'a Buffer,
count_offset: u64,
max_count: u32,
)
pub fn multi_draw_indexed_indirect_count( &mut self, indirect_buffer: &'a Buffer, indirect_offset: u64, count_buffer: &'a Buffer, count_offset: u64, max_count: u32, )
Dispatches multiple draw calls from the active index buffer and the active vertex buffers,
based on the contents of the indirect_buffer.
The count buffer is read to determine how many draws to issue.
The indirect buffer must be long enough to account for max_count draws, however only
count elements will be read, where count is the value read from count_buffer capped
at max_count.
The active index buffer can be set with TrackedRenderPass::set_index_buffer, while the
active vertex buffers can be set with TrackedRenderPass::set_vertex_buffer.
indirect_buffer should contain count tightly packed elements of the following structure:
#[repr(C)]
struct DrawIndexedIndirect {
vertex_count: u32, // The number of vertices to draw.
instance_count: u32, // The number of instances to draw.
first_index: u32, // The base index within the index buffer.
vertex_offset: i32, // The value added to the vertex index before indexing into the vertex buffer.
first_instance: u32, // The instance ID of the first instance to draw.
// has to be 0, unless [`Features::INDIRECT_FIRST_INSTANCE`] is enabled.
}Sourcepub fn set_stencil_reference(&mut self, reference: u32)
pub fn set_stencil_reference(&mut self, reference: u32)
Sets the stencil reference.
Subsequent stencil tests will test against this value.
Sourcepub fn set_scissor_rect(&mut self, x: u32, y: u32, width: u32, height: u32)
pub fn set_scissor_rect(&mut self, x: u32, y: u32, width: u32, height: u32)
Sets the scissor region.
Subsequent draw calls will discard any fragments that fall outside this region.
Sourcepub fn set_immediates(&mut self, offset: u32, data: &[u8])
pub fn set_immediates(&mut self, offset: u32, data: &[u8])
Set immediates data.
Features::IMMEDIATES must be enabled on the device in order to call these functions.
Sourcepub fn set_viewport(
&mut self,
x: f32,
y: f32,
width: f32,
height: f32,
min_depth: f32,
max_depth: f32,
)
pub fn set_viewport( &mut self, x: f32, y: f32, width: f32, height: f32, min_depth: f32, max_depth: f32, )
Set the rendering viewport.
Subsequent draw calls will be projected into that viewport.
Sourcepub fn set_camera_viewport(&mut self, viewport: &Viewport)
pub fn set_camera_viewport(&mut self, viewport: &Viewport)
Set the rendering viewport to the given camera Viewport.
Subsequent draw calls will be projected into that viewport.
Examples found in repository?
679fn custom_draw_system(
680 world: &World,
681 view: ViewQuery<(
682 &ExtractedCamera,
683 &ExtractedView,
684 &ViewTarget,
685 Option<&MainPassResolutionOverride>,
686 )>,
687 stencil_phases: Res<ViewSortedRenderPhases<Stencil3d>>,
688 mut ctx: RenderContext,
689) {
690 let view_entity = view.entity();
691 let (camera, extracted_view, target, resolution_override) = view.into_inner();
692
693 let Some(stencil_phase) = stencil_phases.get(&extracted_view.retained_view_entity) else {
694 return;
695 };
696
697 let mut render_pass = ctx.begin_tracked_render_pass(RenderPassDescriptor {
698 label: Some("stencil pass"),
699 // For the purpose of the example, we will write directly to the view target. A real
700 // stencil pass would write to a custom texture and that texture would be used in later
701 // passes to render custom effects using it.
702 color_attachments: &[Some(target.get_color_attachment())],
703 // We don't bind any depth buffer for this pass
704 depth_stencil_attachment: None,
705 timestamp_writes: None,
706 occlusion_query_set: None,
707 multiview_mask: None,
708 });
709
710 if let Some(viewport) =
711 Viewport::from_viewport_and_override(camera.viewport.as_ref(), resolution_override)
712 {
713 render_pass.set_camera_viewport(&viewport);
714 }
715
716 if let Err(err) = stencil_phase.render(&mut render_pass, world, view_entity) {
717 error!("Error encountered while rendering the stencil phase {err:?}");
718 }
719}More examples
202fn draw_mesh_shader_cubes(
203 mut views: Query<(
204 &ExtractedCamera,
205 &ExtractedView,
206 &ViewTarget,
207 &ViewDepthStencilTexture,
208 &ViewUniformOffset,
209 Option<&MainPassResolutionOverride>,
210 )>,
211 mut render_context: RenderContext,
212 data: Res<MyMeshShaderDrawNode>,
213 view_uniforms: Res<ViewUniforms>,
214 globals: Res<GlobalsBuffer>,
215 pipeline_cache: Res<PipelineCache>,
216) {
217 let Some(mesh_pipeline) = pipeline_cache.get_render_pipeline(data.mesh_pipeline) else {
218 return;
219 };
220
221 for (camera, _, target, depth, view_uniform_offset, resolution_override) in &mut views {
222 let Some(view_binding) = view_uniforms.uniforms.binding() else {
223 return;
224 };
225 let Some(globals_binding) = globals.buffer.binding() else {
226 return;
227 };
228 let bind_group = render_context.render_device().create_bind_group(
229 "custom_task_mesh_bind_group",
230 &pipeline_cache.get_bind_group_layout(&data.layout),
231 &BindGroupEntries::sequential((globals_binding, view_binding)),
232 );
233
234 {
235 let mut pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {
236 label: Some("custom_mesh_shader_pass"),
237 // Write directly to the view target
238 color_attachments: &[Some(target.get_color_attachment())],
239 depth_stencil_attachment: Some(depth.get_attachment(StoreOp::Store)),
240 timestamp_writes: None,
241 occlusion_query_set: None,
242 multiview_mask: None,
243 });
244
245 pass.set_render_pipeline(mesh_pipeline);
246 pass.set_bind_group(0, &bind_group, &[view_uniform_offset.offset]);
247 if let Some(viewport) =
248 Viewport::from_viewport_and_override(camera.viewport.as_ref(), resolution_override)
249 {
250 pass.set_camera_viewport(&viewport);
251 }
252
253 // Since this MeshPipeline has a task shader, this call
254 // dispatches the task shader workgroup
255 pass.draw_mesh_tasks(1, 1, 1);
256 }
257 }
258}637fn main_colored_transparent_pass_2d(
638 world: &World,
639 view: ViewQuery<(
640 &ExtractedCamera,
641 &ExtractedView,
642 &ViewTarget,
643 &ViewDepthStencilTexture,
644 )>,
645 transparent_phases: Res<ViewSortedRenderPhases<TransparentColoredMesh2d>>,
646 mut ctx: RenderContext,
647) {
648 let view_entity = view.entity();
649 let (camera, extracted_view, target, depth) = view.into_inner();
650
651 let Some(transparent_phase) = transparent_phases.get(&extracted_view.retained_view_entity)
652 else {
653 return;
654 };
655
656 #[cfg(feature = "trace")]
657 let _span = info_span!("main_colored_transparent_pass_2d").entered();
658
659 let diagnostics = ctx.diagnostic_recorder();
660 let diagnostics = diagnostics.as_deref();
661
662 let color_attachments = [Some(target.get_color_attachment())];
663 // NOTE: For the transparent pass we load the depth buffer. There should be no
664 // need to write to it, but store is set to `true` as a workaround for issue #3776,
665 // https://github.com/bevyengine/bevy/issues/3776
666 // so that wgpu does not clear the depth buffer.
667 // As the opaque and alpha mask passes run first, opaque meshes can occlude
668 // transparent ones.
669 let depth_stencil_attachment = Some(depth.get_attachment(StoreOp::Store));
670
671 {
672 let mut render_pass = ctx.begin_tracked_render_pass(RenderPassDescriptor {
673 label: Some("main_colored_transparent_pass_2d"),
674 color_attachments: &color_attachments,
675 depth_stencil_attachment,
676 timestamp_writes: None,
677 occlusion_query_set: None,
678 multiview_mask: None,
679 });
680 let pass_span = diagnostics.pass_span(&mut render_pass, "main_colored_transparent_pass_2d");
681
682 if let Some(viewport) = camera.viewport.as_ref() {
683 render_pass.set_camera_viewport(viewport);
684 }
685
686 if !transparent_phase.items.is_empty() {
687 #[cfg(feature = "trace")]
688 let _transparent_span = info_span!("colored_transparent_main_pass_2d").entered();
689 if let Err(err) = transparent_phase.render(&mut render_pass, world, view_entity) {
690 error!(
691 "Error encountered while rendering the colored transparent 2D phase {err:?}"
692 );
693 }
694 }
695
696 pass_span.end(&mut render_pass);
697 }
698}Sourcepub fn insert_debug_marker(&mut self, label: &str)
pub fn insert_debug_marker(&mut self, label: &str)
Insert a single debug marker.
This is a GPU debugging feature. This has no effect on the rendering itself.
Sourcepub fn push_debug_group(&mut self, label: &str)
pub fn push_debug_group(&mut self, label: &str)
Start a new debug group.
Push a new debug group over the internal stack. Subsequent render commands and debug
markers are grouped into this new group, until pop_debug_group is called.
pass.push_debug_group("Render the car");
// [setup pipeline etc...]
pass.draw(0..64, 0..1);
pass.pop_debug_group();Note that push_debug_group and pop_debug_group must always be called in pairs.
This is a GPU debugging feature. This has no effect on the rendering itself.
Sourcepub fn pop_debug_group(&mut self)
pub fn pop_debug_group(&mut self)
End the current debug group.
Subsequent render commands and debug markers are not grouped anymore in this group, but in the previous one (if any) or the default top-level one if the debug group was the last one on the stack.
Note that push_debug_group and pop_debug_group must always be called in pairs.
This is a GPU debugging feature. This has no effect on the rendering itself.
Sourcepub fn set_blend_constant(&mut self, color: LinearRgba)
pub fn set_blend_constant(&mut self, color: LinearRgba)
Sets the blend color as used by some of the blending modes.
Subsequent blending tests will test against this value.
Auto Trait Implementations§
impl<'a> !RefUnwindSafe for TrackedRenderPass<'a>
impl<'a> !UnwindSafe for TrackedRenderPass<'a>
impl<'a> Freeze for TrackedRenderPass<'a>
impl<'a> Send for TrackedRenderPass<'a>
impl<'a> Sync for TrackedRenderPass<'a>
impl<'a> Unpin for TrackedRenderPass<'a>
impl<'a> UnsafeUnpin for TrackedRenderPass<'a>
Blanket Implementations§
Source§impl<T, U> AsBindGroupShaderType<U> for T
impl<T, U> AsBindGroupShaderType<U> for T
Source§fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
T ShaderType for self. When used in AsBindGroup
derives, it is safe to assume that all images in self exist.Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
impl<T> ConditionalSend for Twhere
T: Send,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
impl<S, T> Duplex<S> for Twhere
T: FromSample<S> + ToSample<S>,
impl<T> ErasedDestructor for Twhere
T: 'static,
Source§impl<T> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.Source§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
Source§impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
Source§impl<T> Identity for Twhere
T: ?Sized,
impl<T> Identity for Twhere
T: ?Sized,
Source§impl<T> InitializeFromFunction<T> for T
impl<T> InitializeFromFunction<T> for T
Source§fn initialize_from_function(f: fn() -> T) -> T
fn initialize_from_function(f: fn() -> T) -> T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoResult<T> for T
impl<T> IntoResult<T> for T
Source§fn into_result(self) -> Result<T, RunSystemError>
fn into_result(self) -> Result<T, RunSystemError>
Source§impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
fn into_sample(self) -> T
Source§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
impl<T> Settings for T
Source§impl<Ret> SpawnIfAsync<(), Ret> for Ret
impl<Ret> SpawnIfAsync<(), Ret> for Ret
Source§impl<T, O> SuperFrom<T> for Owhere
O: From<T>,
impl<T, O> SuperFrom<T> for Owhere
O: From<T>,
Source§fn super_from(input: T) -> O
fn super_from(input: T) -> O
Source§impl<T, O, M> SuperInto<O, M> for Twhere
O: SuperFrom<T, M>,
impl<T, O, M> SuperInto<O, M> for Twhere
O: SuperFrom<T, M>,
Source§fn super_into(self) -> O
fn super_into(self) -> O
Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.