Skip to main content

TrackedRenderPass

Struct TrackedRenderPass 

Source
pub struct TrackedRenderPass<'a> { /* private fields */ }
Available on crate feature 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>

Source

pub fn new(device: &RenderDevice, pass: RenderPass<'a>) -> TrackedRenderPass<'a>

Tracks the supplied render pass.

Source

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.

Source

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?
examples/shader_advanced/mesh_shader_intro.rs (line 245)
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
Hide additional examples
examples/shader_advanced/deferred_raymarch.rs (line 282)
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}
Source

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?
examples/2d/mesh2d_manual.rs (line 760)
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
Hide additional examples
examples/shader_advanced/mesh_shader_intro.rs (line 246)
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}
examples/shader_advanced/deferred_raymarch.rs (line 283)
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}
Source

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?
examples/shader_advanced/custom_phase_item.rs (lines 83-90)
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
Hide additional examples
examples/2d/mesh2d_manual.rs (line 801)
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    }
examples/shader_advanced/custom_shader_instancing.rs (line 327)
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    }
Source

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?
examples/shader_advanced/custom_phase_item.rs (lines 93-100)
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
Hide additional examples
examples/2d/mesh2d_manual.rs (line 814)
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    }
examples/shader_advanced/custom_shader_instancing.rs (line 341)
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    }
Source

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?
examples/2d/mesh2d_manual.rs (line 823)
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
Hide additional examples
examples/shader_advanced/custom_shader_instancing.rs (line 349)
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    }
examples/shader_advanced/deferred_raymarch.rs (line 284)
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}
Source

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?
examples/shader_advanced/mesh_shader_intro.rs (line 255)
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}
Source

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,
}
Source

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,
}
Source

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,
}
Source

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?
examples/shader_advanced/custom_phase_item.rs (line 103)
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
Hide additional examples
examples/2d/mesh2d_manual.rs (lines 816-820)
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    }
examples/shader_advanced/custom_shader_instancing.rs (lines 342-346)
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    }
Source

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.
}
Source

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.
}
Source

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.
}
Source

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.
}
Source

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.
}
Source

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.
}
Source

pub fn set_stencil_reference(&mut self, reference: u32)

Sets the stencil reference.

Subsequent stencil tests will test against this value.

Source

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.

Source

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.

Source

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.

Source

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?
examples/shader_advanced/custom_render_phase.rs (line 713)
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
Hide additional examples
examples/shader_advanced/mesh_shader_intro.rs (line 250)
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}
examples/2d/mesh2d_manual.rs (line 683)
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}
Source

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.

Source

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.

Source

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.

Source

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> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T, U> AsBindGroupShaderType<U> for T
where U: ShaderType, &'a T: for<'a> Into<U>,

Source§

fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U

Return the T ShaderType for self. When used in AsBindGroup derives, it is safe to assume that all images in self exist.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> ConditionalSend for T
where T: Send,

Source§

impl<T> Conv for T

Source§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts 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>

Converts 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)

Converts &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)

Converts &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 T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert 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>

Convert 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)

Convert &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)

Convert &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
where T: Any + Send,

Source§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send> ⓘ

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,

Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> FmtForward for T

Source§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
Source§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
Source§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
Source§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
Source§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
Source§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
Source§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
Source§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
Source§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<S> FromSample<S> for S

Source§

fn from_sample_(s: S) -> S

Source§

impl<T, W> HasTypeWitness<W> for T
where W: MakeTypeWitness<Arg = T>, T: ?Sized,

Source§

const WITNESS: W = W::MAKE

A constant of the type witness
Source§

impl<T> Identity for T
where T: ?Sized,

Source§

const TYPE_EQ: TypeEq<T, <T as Identity>::Type> = TypeEq::NEW

Proof that Self is the same type as Self::Type, provides methods for casting between Self and Self::Type.
Source§

type Type = T

The same type as Self, used to emulate type equality bounds (T == U) with associated type equality constraints (T: Identity<Type = U>).
Source§

impl<T> InitializeFromFunction<T> for T

Source§

fn initialize_from_function(f: fn() -> T) -> T

Create an instance of this type from an initialization function
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts 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 more
Source§

impl<T> IntoResult<T> for T

Source§

fn into_result(self) -> Result<T, RunSystemError>

Converts this type into the system output type.
Source§

impl<F, T> IntoSample<T> for F
where T: FromSample<F>,

Source§

fn into_sample(self) -> T

Source§

impl<A> Is for A
where A: Any,

Source§

fn is<T>() -> bool
where T: Any,

Checks if the current type “is” another type, using a TypeId equality comparison. This is most useful in the context of generic logic. Read more
Source§

impl<T> Pipe for T
where T: ?Sized,

Source§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
Source§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
Source§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
Source§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows 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
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows 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
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
Source§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> Settings for T
where T: 'static + Send + Sync,

Source§

impl<Ret> SpawnIfAsync<(), Ret> for Ret

Source§

fn spawn(self) -> Ret

Spawn the value into the dioxus runtime if it is an async block
Source§

impl<T, O> SuperFrom<T> for O
where O: From<T>,

Source§

fn super_from(input: T) -> O

Convert from a type to another type.
Source§

impl<T, O, M> SuperInto<O, M> for T
where O: SuperFrom<T, M>,

Source§

fn super_into(self) -> O

Convert from a type to another type.
Source§

impl<T> Tap for T

Source§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
Source§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
Source§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
Source§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
Source§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
Source§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
Source§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
Source§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
Source§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
Source§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .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
where Self: BorrowMut<B>, B: ?Sized,

Calls .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
where Self: AsRef<R>, R: ?Sized,

Calls .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
where Self: AsMut<R>, R: ?Sized,

Calls .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
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
Source§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

Source§

fn to_sample_(self) -> U

Source§

impl<T> TryConv for T

Source§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more