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
impl MeshAllocator
Sourcepub fn mesh_vertex_slice(
&self,
mesh_id: &AssetId<Mesh>,
) -> Option<SlabAllocationBufferSlice<'_, MeshSlabItem>>
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?
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
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 }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}Sourcepub fn mesh_index_slice(
&self,
mesh_id: &AssetId<Mesh>,
) -> Option<SlabAllocationBufferSlice<'_, MeshSlabItem>>
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?
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
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}Sourcepub fn mesh_morph_target_slice(
&self,
mesh_id: &AssetId<Mesh>,
) -> Option<SlabAllocationBufferSlice<'_, MeshSlabItem>>
Available on crate feature morph only.
pub fn mesh_morph_target_slice( &self, mesh_id: &AssetId<Mesh>, ) -> Option<SlabAllocationBufferSlice<'_, MeshSlabItem>>
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.
Sourcepub fn mesh_slabs(&self, mesh_id: &AssetId<Mesh>) -> Option<MeshSlabs>
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?
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}Sourcepub fn index_allocation_count(&self) -> usize
pub fn index_allocation_count(&self) -> usize
Returns the number of index allocations that this mesh allocator manages.
Sourcepub fn morph_target_slabs(&self) -> impl Iterator<Item = SlabId<MeshSlabItem>>
Available on crate feature morph only.
pub fn morph_target_slabs(&self) -> impl Iterator<Item = SlabId<MeshSlabItem>>
morph only.Returns an iterator over all slabs that contain morph targets.
Methods from Deref<Target = SlabAllocator<MeshSlabItem>>§
Sourcepub fn stage_allocation(&mut self) -> AllocationStage<'_, I>
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.
Sourcepub fn stage_deallocation(&mut self) -> DeallocationStage<'_, I>
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.
Sourcepub fn buffer_for_slab(&self, slab_id: SlabId<I>) -> Option<&Buffer>
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.
Sourcepub fn slab_allocation_slice(
&self,
key: &<I as SlabItem>::Key,
slab_id: SlabId<I>,
) -> Option<SlabAllocationBufferSlice<'_, I>>
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.
Sourcepub fn slab_count(&self) -> usize
pub fn slab_count(&self) -> usize
Get the number of allocated slabs
Sourcepub fn slabs_size(&self) -> u64
pub fn slabs_size(&self) -> u64
Get the total size of all allocated slabs
Sourcepub 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,
)
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
impl Component for MeshAllocator
Source§const STORAGE_TYPE: StorageType = bevy_ecs::component::StorageType::SparseSet
const STORAGE_TYPE: StorageType = bevy_ecs::component::StorageType::SparseSet
Source§type Mutability = Mutable
type Mutability = Mutable
Component<Mutability = Mutable>,
while immutable components will instead have Component<Mutability = Immutable>. Read moreSource§fn register_required_components(
_requiree: ComponentId,
required_components: &mut RequiredComponentsRegistrator<'_, '_>,
)
fn register_required_components( _requiree: ComponentId, required_components: &mut RequiredComponentsRegistrator<'_, '_>, )
Source§fn clone_behavior() -> ComponentCloneBehavior
fn clone_behavior() -> ComponentCloneBehavior
Source§fn relationship_accessor() -> Option<ComponentRelationshipAccessor<MeshAllocator>>
fn relationship_accessor() -> Option<ComponentRelationshipAccessor<MeshAllocator>>
ComponentRelationshipAccessor required for working with relationships in dynamic contexts. Read moreSource§fn on_add() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>
fn on_add() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>
Source§fn on_insert() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>
fn on_insert() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>
Source§fn on_discard() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>
fn on_discard() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>
Source§fn on_remove() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>
fn on_remove() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>
Source§fn on_despawn() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>
fn on_despawn() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>
Source§fn map_entities<E>(_this: &mut Self, _mapper: &mut E)where
E: EntityMapper,
fn map_entities<E>(_this: &mut Self, _mapper: &mut E)where
E: EntityMapper,
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 moreSource§impl Deref for MeshAllocator
impl Deref for MeshAllocator
Source§type Target = SlabAllocator<MeshSlabItem>
type Target = SlabAllocator<MeshSlabItem>
Source§impl DerefMut for MeshAllocator
impl DerefMut for MeshAllocator
Source§impl FromWorld for MeshAllocator
impl FromWorld for MeshAllocator
Source§fn from_world(world: &mut World) -> MeshAllocator
fn from_world(world: &mut World) -> MeshAllocator
Self using data from the given World.impl Resource for MeshAllocator
Auto Trait Implementations§
impl !RefUnwindSafe for MeshAllocator
impl !UnwindSafe for MeshAllocator
impl Freeze for MeshAllocator
impl Send for MeshAllocator
impl Sync for MeshAllocator
impl Unpin for MeshAllocator
impl UnsafeUnpin for MeshAllocator
Blanket Implementations§
Source§impl<T, U> AsBindGroupShaderType<U> for T
impl<T, U> AsBindGroupShaderType<U> for T
Source§fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
T ShaderType for self. When used in AsBindGroup
derives, it is safe to assume that all images in self exist.Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<C> Bundle for Cwhere
C: Component,
impl<C> Bundle for Cwhere
C: Component,
fn component_ids( components: &mut ComponentsRegistrator<'_>, ) -> impl Iterator<Item = ComponentId> + use<C>
Source§fn get_component_ids(
components: &Components,
) -> impl Iterator<Item = Option<ComponentId>>
fn get_component_ids( components: &Components, ) -> impl Iterator<Item = Option<ComponentId>>
Source§impl<C> BundleFromComponents for Cwhere
C: Component,
impl<C> BundleFromComponents for Cwhere
C: Component,
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
impl<T> ConditionalSend for Twhere
T: Send,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
impl<S, T> Duplex<S> for Twhere
T: FromSample<S> + ToSample<S>,
Source§impl<C> DynamicBundle for Cwhere
C: Component,
impl<C> DynamicBundle for Cwhere
C: Component,
Source§unsafe fn get_components(
ptr: MovingPtr<'_, C>,
func: &mut impl FnMut(StorageType, OwningPtr<'_>),
) -> <C as DynamicBundle>::Effect
unsafe fn get_components( ptr: MovingPtr<'_, C>, func: &mut impl FnMut(StorageType, OwningPtr<'_>), ) -> <C as DynamicBundle>::Effect
Source§unsafe fn apply_effect(
_ptr: MovingPtr<'_, MaybeUninit<C>>,
_entity: &mut EntityWorldMut<'_>,
)
unsafe fn apply_effect( _ptr: MovingPtr<'_, MaybeUninit<C>>, _entity: &mut EntityWorldMut<'_>, )
impl<T> ErasedDestructor for Twhere
T: 'static,
Source§impl<T> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.Source§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
Source§impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
Source§impl<T> Identity for Twhere
T: ?Sized,
impl<T> Identity for Twhere
T: ?Sized,
Source§impl<T> InitializeFromFunction<T> for T
impl<T> InitializeFromFunction<T> for T
Source§fn initialize_from_function(f: fn() -> T) -> T
fn initialize_from_function(f: fn() -> T) -> T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoResult<T> for T
impl<T> IntoResult<T> for T
Source§fn into_result(self) -> Result<T, RunSystemError>
fn into_result(self) -> Result<T, RunSystemError>
Source§impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
fn into_sample(self) -> T
Source§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
impl<T> Settings for T
Source§impl<Ret> SpawnIfAsync<(), Ret> for Ret
impl<Ret> SpawnIfAsync<(), Ret> for Ret
Source§impl<T, O> SuperFrom<T> for Owhere
O: From<T>,
impl<T, O> SuperFrom<T> for Owhere
O: From<T>,
Source§fn super_from(input: T) -> O
fn super_from(input: T) -> O
Source§impl<T, O, M> SuperInto<O, M> for Twhere
O: SuperFrom<T, M>,
impl<T, O, M> SuperInto<O, M> for Twhere
O: SuperFrom<T, M>,
Source§fn super_into(self) -> O
fn super_into(self) -> O
Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.