Skip to main content

MeshAllocator

Struct MeshAllocator 

Source
pub struct MeshAllocator { /* private fields */ }
Expand description

Manages the assignment of mesh data to GPU buffers.

The Bevy renderer tries to pack vertex and index data for multiple meshes together so that multiple meshes can be drawn back-to-back without any rebinding. This resource manages these buffers.

The MeshAllocatorSettings allows you to tune the behavior of the allocator for better performance with your use case. Most applications won’t need to change the settings from their default values.

Implementations§

Source§

impl MeshAllocator

Source

pub fn mesh_vertex_slice( &self, mesh_id: &AssetId<Mesh>, ) -> Option<SlabAllocationBufferSlice<'_, MeshSlabItem>>

Returns the buffer and range within that buffer of the vertex data for the mesh with the given ID.

If the mesh wasn’t allocated, returns None.

Examples found in repository?
examples/shader_advanced/custom_render_phase.rs (line 379)
363    fn get_batch_data(
364        (mesh_instances, _render_assets, mesh_allocator): &SystemParamItem<Self::Param>,
365        (_entity, main_entity): (Entity, MainEntity),
366    ) -> Option<(
367        Self::BufferData,
368        Option<(Self::BatchSetCompareData, Self::BatchCompareData)>,
369    )> {
370        let RenderMeshInstances::CpuBuilding(ref mesh_instances) = **mesh_instances else {
371            error!(
372                "`get_batch_data` should never be called in GPU mesh uniform \
373                building mode"
374            );
375            return None;
376        };
377        let mesh_instance = mesh_instances.get(&main_entity)?;
378        let first_vertex_index =
379            match mesh_allocator.mesh_vertex_slice(&mesh_instance.mesh_asset_id()) {
380                Some(mesh_vertex_slice) => mesh_vertex_slice.range.start,
381                None => 0,
382            };
383        let mesh_uniform = {
384            let mesh_transforms = &mesh_instance.transforms;
385            let (local_from_world_transpose_a, local_from_world_transpose_b) =
386                mesh_transforms.world_from_local.inverse_transpose_3x3();
387            MeshUniform {
388                world_from_local: mesh_transforms.world_from_local.to_transpose(),
389                previous_world_from_local: mesh_transforms.previous_world_from_local.to_transpose(),
390                lightmap_uv_rect: UVec2::ZERO,
391                local_from_world_transpose_a,
392                local_from_world_transpose_b,
393                flags: mesh_transforms.flags,
394                first_vertex_index,
395                current_skin_index: u32::MAX,
396                material_and_lightmap_bind_group_slot: 0,
397                tag: 0,
398                morph_descriptor_index: u32::MAX,
399            }
400        };
401        Some((mesh_uniform, None))
402    }
403}
404
405impl GetFullBatchData for StencilPipeline {
406    type BufferInputData = MeshInputUniform;
407
408    fn get_index_and_compare_data(
409        (mesh_instances, _, _): &SystemParamItem<Self::Param>,
410        main_entity: MainEntity,
411    ) -> Option<(
412        NonMaxU32,
413        Option<(Self::BatchSetCompareData, Self::BatchCompareData)>,
414    )> {
415        // This should only be called during GPU building.
416        let RenderMeshInstances::GpuBuilding(ref mesh_instances) = **mesh_instances else {
417            error!(
418                "`get_index_and_compare_data` should never be called in CPU mesh uniform building \
419                mode"
420            );
421            return None;
422        };
423        let mesh_instance = mesh_instances.get(&main_entity)?;
424        Some((
425            NonMaxU32::new(mesh_instance.gpu_specific.current_uniform_index())?,
426            mesh_instance
427                .should_batch()
428                .then_some((mesh_instance.mesh_asset_id(), ())),
429        ))
430    }
431
432    fn get_binned_batch_data(
433        (mesh_instances, _render_assets, mesh_allocator): &SystemParamItem<Self::Param>,
434        main_entity: MainEntity,
435    ) -> Option<Self::BufferData> {
436        let RenderMeshInstances::CpuBuilding(ref mesh_instances) = **mesh_instances else {
437            error!(
438                "`get_binned_batch_data` should never be called in GPU mesh uniform building mode"
439            );
440            return None;
441        };
442        let mesh_instance = mesh_instances.get(&main_entity)?;
443        let first_vertex_index =
444            match mesh_allocator.mesh_vertex_slice(&mesh_instance.mesh_asset_id()) {
445                Some(mesh_vertex_slice) => mesh_vertex_slice.range.start,
446                None => 0,
447            };
448
449        Some(MeshUniform::new(
450            &mesh_instance.transforms,
451            first_vertex_index,
452            mesh_instance.material_bindings_index().slot,
453            None,
454            None,
455            None,
456            None,
457        ))
458    }
More examples
Hide additional examples
examples/shader_advanced/custom_shader_instancing.rs (line 322)
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/compute_mesh.rs (line 272)
253fn compute_mesh(
254    mut render_context: RenderContext,
255    chunks: Res<ChunksToProcess>,
256    mesh_allocator: Res<MeshAllocator>,
257    pipeline_cache: Res<PipelineCache>,
258    pipeline: Res<ComputePipeline>,
259    render_queue: Res<RenderQueue>,
260) {
261    let Some(init_pipeline) = pipeline_cache.get_compute_pipeline(pipeline.pipeline) else {
262        return;
263    };
264
265    for mesh_id in &chunks.0 {
266        info!(?mesh_id, "processing mesh");
267
268        // the mesh_allocator holds slabs of meshes, so the buffers we get here
269        // can contain more data than just the mesh we're asking for.
270        // That's why there is a range field.
271        // You should *not* touch data in these buffers that is outside of the range.
272        let vertex_buffer_slice = mesh_allocator.mesh_vertex_slice(mesh_id).unwrap();
273        let index_buffer_slice = mesh_allocator.mesh_index_slice(mesh_id).unwrap();
274
275        let first = DataRanges {
276            // there are 8 vertex data values (pos, normal, uv) per vertex
277            // and the vertex_buffer_slice.range.start is in "vertex elements"
278            // which includes all of that data, so each index is worth 8 indices
279            // to our shader code.
280            vertex_start: vertex_buffer_slice.range.start * 8,
281            vertex_end: vertex_buffer_slice.range.end * 8,
282            // but each vertex index is a single value, so the index of the
283            // vertex indices is exactly what the value is
284            index_start: index_buffer_slice.range.start,
285            index_end: index_buffer_slice.range.end,
286        };
287
288        let mut uniforms = UniformBuffer::from(first);
289        uniforms.write_buffer(render_context.render_device(), &render_queue);
290
291        // pass in the full mesh_allocator slabs as well as the first index
292        // offsets for the vertex and index buffers
293        let bind_group = render_context.render_device().create_bind_group(
294            None,
295            &pipeline_cache.get_bind_group_layout(&pipeline.layout),
296            &BindGroupEntries::sequential((
297                &uniforms,
298                vertex_buffer_slice.buffer.as_entire_buffer_binding(),
299                index_buffer_slice.buffer.as_entire_buffer_binding(),
300            )),
301        );
302
303        let mut pass =
304            render_context
305                .command_encoder()
306                .begin_compute_pass(&ComputePassDescriptor {
307                    label: Some("Mesh generation compute pass"),
308                    ..default()
309                });
310        pass.push_debug_group("compute_mesh");
311
312        pass.set_bind_group(0, &bind_group, &[]);
313        pass.set_pipeline(init_pipeline);
314        // we only dispatch 1,1,1 workgroup here, but a real compute shader
315        // would take advantage of more and larger size workgroups
316        pass.dispatch_workgroups(1, 1, 1);
317
318        pass.pop_debug_group();
319    }
320}
Source

pub fn mesh_index_slice( &self, mesh_id: &AssetId<Mesh>, ) -> Option<SlabAllocationBufferSlice<'_, MeshSlabItem>>

Returns the buffer and range within that buffer of the index data for the mesh with the given ID.

If the mesh has no index data or wasn’t allocated, returns None.

Examples found in repository?
examples/shader_advanced/custom_shader_instancing.rs (line 336)
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    }
More examples
Hide additional examples
examples/shader_advanced/compute_mesh.rs (line 273)
253fn compute_mesh(
254    mut render_context: RenderContext,
255    chunks: Res<ChunksToProcess>,
256    mesh_allocator: Res<MeshAllocator>,
257    pipeline_cache: Res<PipelineCache>,
258    pipeline: Res<ComputePipeline>,
259    render_queue: Res<RenderQueue>,
260) {
261    let Some(init_pipeline) = pipeline_cache.get_compute_pipeline(pipeline.pipeline) else {
262        return;
263    };
264
265    for mesh_id in &chunks.0 {
266        info!(?mesh_id, "processing mesh");
267
268        // the mesh_allocator holds slabs of meshes, so the buffers we get here
269        // can contain more data than just the mesh we're asking for.
270        // That's why there is a range field.
271        // You should *not* touch data in these buffers that is outside of the range.
272        let vertex_buffer_slice = mesh_allocator.mesh_vertex_slice(mesh_id).unwrap();
273        let index_buffer_slice = mesh_allocator.mesh_index_slice(mesh_id).unwrap();
274
275        let first = DataRanges {
276            // there are 8 vertex data values (pos, normal, uv) per vertex
277            // and the vertex_buffer_slice.range.start is in "vertex elements"
278            // which includes all of that data, so each index is worth 8 indices
279            // to our shader code.
280            vertex_start: vertex_buffer_slice.range.start * 8,
281            vertex_end: vertex_buffer_slice.range.end * 8,
282            // but each vertex index is a single value, so the index of the
283            // vertex indices is exactly what the value is
284            index_start: index_buffer_slice.range.start,
285            index_end: index_buffer_slice.range.end,
286        };
287
288        let mut uniforms = UniformBuffer::from(first);
289        uniforms.write_buffer(render_context.render_device(), &render_queue);
290
291        // pass in the full mesh_allocator slabs as well as the first index
292        // offsets for the vertex and index buffers
293        let bind_group = render_context.render_device().create_bind_group(
294            None,
295            &pipeline_cache.get_bind_group_layout(&pipeline.layout),
296            &BindGroupEntries::sequential((
297                &uniforms,
298                vertex_buffer_slice.buffer.as_entire_buffer_binding(),
299                index_buffer_slice.buffer.as_entire_buffer_binding(),
300            )),
301        );
302
303        let mut pass =
304            render_context
305                .command_encoder()
306                .begin_compute_pass(&ComputePassDescriptor {
307                    label: Some("Mesh generation compute pass"),
308                    ..default()
309                });
310        pass.push_debug_group("compute_mesh");
311
312        pass.set_bind_group(0, &bind_group, &[]);
313        pass.set_pipeline(init_pipeline);
314        // we only dispatch 1,1,1 workgroup here, but a real compute shader
315        // would take advantage of more and larger size workgroups
316        pass.dispatch_workgroups(1, 1, 1);
317
318        pass.pop_debug_group();
319    }
320}
Source

pub fn mesh_morph_target_slice( &self, mesh_id: &AssetId<Mesh>, ) -> Option<SlabAllocationBufferSlice<'_, MeshSlabItem>>

Available on crate feature morph only.

Returns the buffer and range within that buffer of the morph target data for the mesh with the given ID.

If the mesh has no morph target data or wasn’t allocated, returns None.

Source

pub fn mesh_slabs(&self, mesh_id: &AssetId<Mesh>) -> Option<MeshSlabs>

Returns the IDs of the vertex buffer and index buffer respectively for the mesh with the given ID.

If the mesh wasn’t allocated, or has no index data in the case of the index buffer, the corresponding element in the returned tuple will be None.

Examples found in repository?
examples/shader_advanced/specialized_mesh_pipeline.rs (line 355)
277fn queue_custom_mesh_pipeline(
278    pipeline_cache: Res<PipelineCache>,
279    custom_mesh_pipeline: Res<CustomMeshPipeline>,
280    (mut opaque_render_phases, opaque_draw_functions): (
281        ResMut<ViewBinnedRenderPhases<Opaque3d>>,
282        Res<DrawFunctions<Opaque3d>>,
283    ),
284    mut specialized_mesh_pipelines: ResMut<SpecializedMeshPipelines<CustomMeshPipeline>>,
285    views: Query<(&RenderVisibleEntities, &ExtractedView)>,
286    view_key_cache: Res<ViewKeyCache>,
287    (render_meshes, render_mesh_instances): (
288        Res<RenderAssets<RenderMesh>>,
289        Res<RenderMeshInstances>,
290    ),
291    mut change_tick: Local<Tick>,
292    mesh_allocator: Res<MeshAllocator>,
293    gpu_preprocessing_support: Res<GpuPreprocessingSupport>,
294    dirty_specializations: Res<DirtySpecializations>,
295    mut pending_custom_mesh_queues: ResMut<PendingCustomMeshQueues>,
296) {
297    // Get the id for our custom draw function
298    let draw_function = opaque_draw_functions
299        .read()
300        .id::<DrawSpecializedPipelineCommands>();
301
302    // Render phases are per-view, so we need to iterate over all views so that
303    // the entity appears in them. (In this example, we have only one view, but
304    // it's good practice to loop over all views anyway.)
305    for (view_visible_entities, view) in views.iter() {
306        let Some(opaque_phase) = opaque_render_phases.get_mut(&view.retained_view_entity) else {
307            continue;
308        };
309
310        let Some(&view_key) = view_key_cache.get(&view.retained_view_entity) else {
311            continue;
312        };
313
314        let Some(render_visible_mesh_entities) =
315            view_visible_entities.get::<CustomRenderedEntity>()
316        else {
317            continue;
318        };
319
320        // Initialize the pending queues.
321        let view_pending_custom_mesh_queues =
322            pending_custom_mesh_queues.prepare_for_new_frame(view.retained_view_entity);
323
324        // First, remove meshes that need to be respecialized, and those that were removed, from the bins.
325        for &main_entity in dirty_specializations
326            .iter_to_dequeue(view.retained_view_entity, render_visible_mesh_entities)
327        {
328            opaque_phase.remove(main_entity);
329        }
330
331        // Find all the custom rendered entities that are visible from this
332        // view.
333        for (render_entity, visible_entity) in dirty_specializations.iter_to_queue(
334            view.retained_view_entity,
335            render_visible_mesh_entities,
336            &view_pending_custom_mesh_queues.prev_frame,
337        ) {
338            // Get the mesh instance
339            let Some(mesh_instance) = render_mesh_instances.render_mesh_queue_data(*visible_entity)
340            else {
341                // We couldn't fetch the mesh, probably because it hasn't been
342                // loaded yet. Add the entity to the list of pending custom
343                // meshes and bail.
344                view_pending_custom_mesh_queues
345                    .current_frame
346                    .insert((*render_entity, *visible_entity));
347                continue;
348            };
349
350            // Get the mesh data
351            let Some(mesh) = render_meshes.get(mesh_instance.mesh_asset_id()) else {
352                continue;
353            };
354
355            let Some(mesh_slabs) = mesh_allocator.mesh_slabs(&mesh_instance.mesh_asset_id()) else {
356                continue;
357            };
358
359            // Specialize the key for the current mesh entity
360            // For this example we only specialize based on the mesh topology
361            // but you could have more complex keys and that's where you'd need to create those keys
362            let mut mesh_key = view_key;
363            mesh_key |= MeshPipelineKey::from_primitive_topology_and_strip_index(
364                mesh.primitive_topology(),
365                mesh.index_format(),
366            );
367
368            // Finally, we can specialize the pipeline based on the key
369            let pipeline_id = specialized_mesh_pipelines
370                .specialize(
371                    &pipeline_cache,
372                    &custom_mesh_pipeline,
373                    mesh_key,
374                    &mesh.layout,
375                )
376                // This should never happen with this example, but if your pipeline
377                // specialization can fail you need to handle the error here
378                .expect("Failed to specialize mesh pipeline");
379
380            // Bump the change tick so that Bevy is forced to rebuild the bin.
381            let next_change_tick = change_tick.get() + 1;
382            change_tick.set(next_change_tick);
383
384            // Add the mesh with our specialized pipeline
385            opaque_phase.add(
386                Opaque3dBatchSetKey {
387                    draw_function,
388                    pipeline: pipeline_id,
389                    material_bind_group_index: None,
390                    slabs: mesh_slabs,
391                    lightmap_slab: None,
392                },
393                // For this example we can use the mesh asset id as the bin key,
394                // but you can use any asset_id as a key
395                Opaque3dBinKey {
396                    asset_id: mesh_instance.mesh_asset_id().into(),
397                },
398                (*render_entity, *visible_entity),
399                mesh_instance.current_uniform_index,
400                // This example supports batching and multi draw indirect,
401                // but if your pipeline doesn't support it you can use
402                // `BinnedRenderPhaseType::UnbatchableMesh`
403                BinnedRenderPhaseType::mesh(
404                    mesh_instance.should_batch(),
405                    &gpu_preprocessing_support,
406                ),
407            );
408        }
409    }
410}
Source

pub fn index_allocation_count(&self) -> usize

Returns the number of index allocations that this mesh allocator manages.

Source

pub fn morph_target_slabs(&self) -> impl Iterator<Item = SlabId<MeshSlabItem>>

Available on crate feature morph only.

Returns an iterator over all slabs that contain morph targets.

Methods from Deref<Target = SlabAllocator<MeshSlabItem>>§

Source

pub fn stage_allocation(&mut self) -> AllocationStage<'_, I>

Creates an AllocationStage, enabling batched allocation of objects in this slab.

Allocation of objects in the slab requires calling this function, calling AllocationStage::allocate on the resulting AllocationStage, and finally calling AllocationStage::commit. Grouping allocations into a batch, preferably at most one per frame, is the most efficient way to perform many allocations at once.

Source

pub fn stage_deallocation(&mut self) -> DeallocationStage<'_, I>

Creates a DeallocationStage, enabling batched deallocation.

Deallocation of objects in the slab requires calling this function, calling DeallocationStage::free on the resulting DeallocationStage, and finally calling DeallocationStage::commit. Grouping deallocations into a batch, preferably at most one per frame, is the most efficient way to perform many deallocations at once.

Source

pub fn buffer_for_slab(&self, slab_id: SlabId<I>) -> Option<&Buffer>

Returns the GPU buffer corresponding to the slab with the given ID if that slab has been uploaded to the GPU.

Source

pub fn slab_allocation_slice( &self, key: &<I as SlabItem>::Key, slab_id: SlabId<I>, ) -> Option<SlabAllocationBufferSlice<'_, I>>

Given a slab and the key of data located with it, returns the buffer and range of that data within the slab.

Source

pub fn slab_count(&self) -> usize

Get the number of allocated slabs

Source

pub fn slabs_size(&self) -> u64

Get the total size of all allocated slabs

Source

pub fn copy_element_data( &mut self, key: &<I as SlabItem>::Key, len: usize, fill_data: impl Fn(WriteOnly<'_, [u8]>), render_device: &RenderDevice, render_queue: &RenderQueue, )

Copies data into an allocated slab.

len specifies the size of the data to be copied in bytes. The given fill_data callback is expected to write the data into the given slice; this callback approach avoids a copy.

Trait Implementations§

Source§

impl Component for MeshAllocator
where MeshAllocator: Send + Sync + 'static,

Source§

const STORAGE_TYPE: StorageType = bevy_ecs::component::StorageType::SparseSet

A constant indicating the storage type used for this component.
Source§

type Mutability = Mutable

A marker type to assist Bevy with determining if this component is mutable, or immutable. Mutable components will have Component<Mutability = Mutable>, while immutable components will instead have Component<Mutability = Immutable>. Read more
Source§

fn register_required_components( _requiree: ComponentId, required_components: &mut RequiredComponentsRegistrator<'_, '_>, )

Registers required components. Read more
Source§

fn clone_behavior() -> ComponentCloneBehavior

Called when registering this component, allowing to override clone function (or disable cloning altogether) for this component. Read more
Source§

fn relationship_accessor() -> Option<ComponentRelationshipAccessor<MeshAllocator>>

Returns ComponentRelationshipAccessor required for working with relationships in dynamic contexts. Read more
Source§

fn on_add() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>

Gets the on_add ComponentHook for this Component if one is defined.
Source§

fn on_insert() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>

Gets the on_insert ComponentHook for this Component if one is defined.
Source§

fn on_discard() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>

Gets the on_discard ComponentHook for this Component if one is defined.
Source§

fn on_remove() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>

Gets the on_remove ComponentHook for this Component if one is defined.
Source§

fn on_despawn() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>

Gets the on_despawn ComponentHook for this Component if one is defined.
Source§

fn map_entities<E>(_this: &mut Self, _mapper: &mut E)
where E: EntityMapper,

Maps the entities on this component using the given EntityMapper. This is used to remap entities in contexts like scenes and entity cloning. When deriving Component, this is populated by annotating fields containing entities with #[entities] Read more
Source§

impl Deref for MeshAllocator

Source§

type Target = SlabAllocator<MeshSlabItem>

The resulting type after dereferencing.
Source§

fn deref(&self) -> &<MeshAllocator as Deref>::Target

Dereferences the value.
Source§

impl DerefMut for MeshAllocator

Source§

fn deref_mut(&mut self) -> &mut <MeshAllocator as Deref>::Target

Mutably dereferences the value.
Source§

impl FromWorld for MeshAllocator

Source§

fn from_world(world: &mut World) -> MeshAllocator

Creates Self using data from the given World.
Source§

impl Resource for MeshAllocator
where MeshAllocator: Send + Sync + 'static,

Auto Trait Implementations§

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<C> Bundle for C
where C: Component,

Source§

fn component_ids( components: &mut ComponentsRegistrator<'_>, ) -> impl Iterator<Item = ComponentId> + use<C>

Source§

fn get_component_ids( components: &Components, ) -> impl Iterator<Item = Option<ComponentId>>

Return a iterator over this Bundle’s component ids. This will be None if the component has not been registered.
Source§

impl<C> BundleFromComponents for C
where C: Component,

Source§

unsafe fn from_components<T, F>(ctx: &mut T, func: &mut F) -> C
where F: for<'a> FnMut(&'a mut T) -> OwningPtr<'a>, C: Sized,

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 + Send + Sync>

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<C> DynamicBundle for C
where C: Component,

Source§

type Effect = ()

An operation on the entity that happens after inserting this bundle.
Source§

unsafe fn get_components( ptr: MovingPtr<'_, C>, func: &mut impl FnMut(StorageType, OwningPtr<'_>), ) -> <C as DynamicBundle>::Effect

Moves the components out of the bundle. Read more
Source§

unsafe fn apply_effect( _ptr: MovingPtr<'_, MaybeUninit<C>>, _entity: &mut EntityWorldMut<'_>, )

Applies the after-effects of spawning this bundle. Read more
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<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
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 = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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