diff --git a/crates/bevy_gizmos/src/lib.rs b/crates/bevy_gizmos/src/lib.rs index e194701e76..2e406a3c5e 100644 --- a/crates/bevy_gizmos/src/lib.rs +++ b/crates/bevy_gizmos/src/lib.rs @@ -383,10 +383,13 @@ impl RenderCommand

for SetLineGizmoBindGroup fn render<'w>( _item: &P, _view: ROQueryItem<'w, Self::ViewQuery>, - uniform_index: ROQueryItem<'w, Self::ItemQuery>, + uniform_index: Option>, bind_group: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { + let Some(uniform_index) = uniform_index else { + return RenderCommandResult::Failure; + }; pass.set_bind_group( I, &bind_group.into_inner().bindgroup, @@ -406,10 +409,13 @@ impl RenderCommand

for DrawLineGizmo { fn render<'w>( _item: &P, _view: ROQueryItem<'w, Self::ViewQuery>, - handle: ROQueryItem<'w, Self::ItemQuery>, + handle: Option>, line_gizmos: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { + let Some(handle) = handle else { + return RenderCommandResult::Failure; + }; let Some(line_gizmo) = line_gizmos.into_inner().get(handle) else { return RenderCommandResult::Failure; }; diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 10e39448dd..a4a8eb8401 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -388,7 +388,7 @@ impl RenderCommand

for SetMaterial fn render<'w>( item: &P, _view: (), - _item_query: (), + _item_query: Option<()>, (materials, material_instances): SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index 00380acdc8..8c2fb33d3b 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -912,7 +912,7 @@ impl RenderCommand

for SetPrepassViewBindGroup< &'_ ViewUniformOffset, Option<&'_ PreviousViewProjectionUniformOffset>, ), - _entity: (), + _entity: Option<()>, prepass_view_bind_group: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 5a422727b2..11a2cce0f2 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -256,12 +256,7 @@ pub struct RenderMeshInstance { #[derive(Default, Resource, Deref, DerefMut)] pub struct RenderMeshInstances(EntityHashMap); -#[derive(Component)] -pub struct Mesh3d; - pub fn extract_meshes( - mut commands: Commands, - mut previous_len: Local, mut render_mesh_instances: ResMut, mut thread_local_queues: Local>>>, meshes_query: Extract< @@ -328,15 +323,9 @@ pub fn extract_meshes( ); render_mesh_instances.clear(); - let mut entities = Vec::with_capacity(*previous_len); for queue in thread_local_queues.iter_mut() { - // FIXME: Remove this - it is just a workaround to enable rendering to work as - // render commands require an entity to exist at the moment. - entities.extend(queue.get_mut().iter().map(|(e, _)| (*e, Mesh3d))); render_mesh_instances.extend(queue.get_mut().drain(..)); } - *previous_len = entities.len(); - commands.insert_or_spawn_batch(entities); } #[derive(Resource, Clone)] @@ -1050,7 +1039,7 @@ impl RenderCommand

for SetMeshViewBindGroup 'w, Self::ViewQuery, >, - _entity: (), + _entity: Option<()>, _: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { @@ -1085,7 +1074,7 @@ impl RenderCommand

for SetMeshBindGroup { fn render<'w>( item: &P, _view: (), - _item_query: (), + _item_query: Option<()>, (bind_groups, mesh_instances, skin_indices, morph_indices, lightmaps): SystemParamItem< 'w, '_, @@ -1154,7 +1143,7 @@ impl RenderCommand

for DrawMesh { fn render<'w>( item: &P, _view: (), - _item_query: (), + _item_query: Option<()>, (meshes, mesh_instances): SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { diff --git a/crates/bevy_render/src/render_phase/draw.rs b/crates/bevy_render/src/render_phase/draw.rs index f67316d68a..aa05fa3e49 100644 --- a/crates/bevy_render/src/render_phase/draw.rs +++ b/crates/bevy_render/src/render_phase/draw.rs @@ -190,6 +190,11 @@ pub trait RenderCommand { /// /// The item is the entity that will be rendered for the corresponding view. /// All components have to be accessed read only. + /// + /// For efficiency reasons, Bevy doesn't always extract entities to the + /// render world; for instance, entities that simply consist of meshes are + /// often not extracted. If the entity doesn't exist in the render world, + /// the supplied query data will be `None`. type ItemQuery: ReadOnlyQueryData; /// Renders a [`PhaseItem`] by recording commands (e.g. setting pipelines, binding bind groups, @@ -197,7 +202,7 @@ pub trait RenderCommand { fn render<'w>( item: &P, view: ROQueryItem<'w, Self::ViewQuery>, - entity: ROQueryItem<'w, Self::ItemQuery>, + entity: Option>, param: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult; @@ -220,13 +225,22 @@ macro_rules! render_command_tuple_impl { fn render<'w>( _item: &P, ($($view,)*): ROQueryItem<'w, Self::ViewQuery>, - ($($entity,)*): ROQueryItem<'w, Self::ItemQuery>, + maybe_entities: Option>, ($($name,)*): SystemParamItem<'w, '_, Self::Param>, _pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { - $(if let RenderCommandResult::Failure = $name::render(_item, $view, $entity, $name, _pass) { - return RenderCommandResult::Failure; - })* + match maybe_entities { + None => { + $(if let RenderCommandResult::Failure = $name::render(_item, $view, None, $name, _pass) { + return RenderCommandResult::Failure; + })* + } + Some(($($entity,)*)) => { + $(if let RenderCommandResult::Failure = $name::render(_item, $view, Some($entity), $name, _pass) { + return RenderCommandResult::Failure; + })* + } + } RenderCommandResult::Success } } @@ -278,7 +292,7 @@ where ) { let param = self.state.get_manual(world); let view = self.view.get_manual(world, view).unwrap(); - let entity = self.entity.get_manual(world, item.entity()).unwrap(); + let entity = self.entity.get_manual(world, item.entity()).ok(); // TODO: handle/log `RenderCommand` failure C::render(item, view, entity, param, pass); } diff --git a/crates/bevy_render/src/render_phase/mod.rs b/crates/bevy_render/src/render_phase/mod.rs index df804bfad1..e66698fc37 100644 --- a/crates/bevy_render/src/render_phase/mod.rs +++ b/crates/bevy_render/src/render_phase/mod.rs @@ -202,7 +202,7 @@ impl RenderCommand

for SetItemPipeline { fn render<'w>( item: &P, _view: (), - _entity: (), + _entity: Option<()>, pipeline_cache: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { diff --git a/crates/bevy_sprite/src/mesh2d/material.rs b/crates/bevy_sprite/src/mesh2d/material.rs index 07626d47a5..768ebf067c 100644 --- a/crates/bevy_sprite/src/mesh2d/material.rs +++ b/crates/bevy_sprite/src/mesh2d/material.rs @@ -337,7 +337,7 @@ impl RenderCommand

fn render<'w>( item: &P, _view: (), - _item_query: (), + _item_query: Option<()>, (materials, material_instances): SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { diff --git a/crates/bevy_sprite/src/mesh2d/mesh.rs b/crates/bevy_sprite/src/mesh2d/mesh.rs index efd2a7ac67..cf66740f38 100644 --- a/crates/bevy_sprite/src/mesh2d/mesh.rs +++ b/crates/bevy_sprite/src/mesh2d/mesh.rs @@ -624,7 +624,7 @@ impl RenderCommand

for SetMesh2dViewBindGroup( _item: &P, (view_uniform, mesh2d_view_bind_group): ROQueryItem<'w, Self::ViewQuery>, - _view: (), + _view: Option<()>, _param: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { @@ -644,7 +644,7 @@ impl RenderCommand

for SetMesh2dBindGroup { fn render<'w>( item: &P, _view: (), - _item_query: (), + _item_query: Option<()>, mesh2d_bind_group: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { @@ -673,7 +673,7 @@ impl RenderCommand

for DrawMesh2d { fn render<'w>( item: &P, _view: (), - _item_query: (), + _item_query: Option<()>, (meshes, render_mesh2d_instances): SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { diff --git a/crates/bevy_sprite/src/render/mod.rs b/crates/bevy_sprite/src/render/mod.rs index f66a65e6d6..72177821f3 100644 --- a/crates/bevy_sprite/src/render/mod.rs +++ b/crates/bevy_sprite/src/render/mod.rs @@ -752,7 +752,7 @@ impl RenderCommand

for SetSpriteViewBindGroup( _item: &P, view_uniform: &'_ ViewUniformOffset, - _entity: (), + _entity: Option<()>, sprite_meta: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { @@ -773,11 +773,14 @@ impl RenderCommand

for SetSpriteTextureBindGrou fn render<'w>( _item: &P, _view: (), - batch: &'_ SpriteBatch, + batch: Option<&'_ SpriteBatch>, image_bind_groups: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { let image_bind_groups = image_bind_groups.into_inner(); + let Some(batch) = batch else { + return RenderCommandResult::Failure; + }; pass.set_bind_group( I, @@ -800,11 +803,15 @@ impl RenderCommand

for DrawSpriteBatch { fn render<'w>( _item: &P, _view: (), - batch: &'_ SpriteBatch, + batch: Option<&'_ SpriteBatch>, sprite_meta: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { let sprite_meta = sprite_meta.into_inner(); + let Some(batch) = batch else { + return RenderCommandResult::Failure; + }; + pass.set_index_buffer( sprite_meta.sprite_index_buffer.buffer().unwrap().slice(..), 0, diff --git a/crates/bevy_ui/src/render/render_pass.rs b/crates/bevy_ui/src/render/render_pass.rs index a38a14d234..e0119509d7 100644 --- a/crates/bevy_ui/src/render/render_pass.rs +++ b/crates/bevy_ui/src/render/render_pass.rs @@ -161,7 +161,7 @@ impl RenderCommand

for SetUiViewBindGroup { fn render<'w>( _item: &P, view_uniform: &'w ViewUniformOffset, - _entity: (), + _entity: Option<()>, ui_meta: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { @@ -183,11 +183,15 @@ impl RenderCommand

for SetUiTextureBindGroup fn render<'w>( _item: &P, _view: (), - batch: &'w UiBatch, + batch: Option<&'w UiBatch>, image_bind_groups: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { let image_bind_groups = image_bind_groups.into_inner(); + let Some(batch) = batch else { + return RenderCommandResult::Failure; + }; + pass.set_bind_group(I, image_bind_groups.values.get(&batch.image).unwrap(), &[]); RenderCommandResult::Success } @@ -202,10 +206,14 @@ impl RenderCommand

for DrawUiNode { fn render<'w>( _item: &P, _view: (), - batch: &'w UiBatch, + batch: Option<&'w UiBatch>, ui_meta: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { + let Some(batch) = batch else { + return RenderCommandResult::Failure; + }; + pass.set_vertex_buffer(0, ui_meta.into_inner().vertices.buffer().unwrap().slice(..)); pass.draw(batch.range.clone(), 0..1); RenderCommandResult::Success diff --git a/crates/bevy_ui/src/render/ui_material_pipeline.rs b/crates/bevy_ui/src/render/ui_material_pipeline.rs index 1afead26ce..21dbe62f0c 100644 --- a/crates/bevy_ui/src/render/ui_material_pipeline.rs +++ b/crates/bevy_ui/src/render/ui_material_pipeline.rs @@ -272,7 +272,7 @@ impl RenderCommand

for SetMatUiV fn render<'w>( _item: &P, view_uniform: &'w ViewUniformOffset, - _entity: (), + _entity: Option<()>, ui_meta: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { @@ -296,10 +296,13 @@ impl RenderCommand

fn render<'w>( _item: &P, _view: (), - material_handle: ROQueryItem<'_, Self::ItemQuery>, + material_handle: Option>, materials: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { + let Some(material_handle) = material_handle else { + return RenderCommandResult::Failure; + }; let Some(material) = materials.into_inner().get(&material_handle.material) else { return RenderCommandResult::Failure; }; @@ -318,10 +321,14 @@ impl RenderCommand

for DrawUiMaterialNode { fn render<'w>( _item: &P, _view: (), - batch: &'w UiMaterialBatch, + batch: Option<&'w UiMaterialBatch>, ui_meta: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { + let Some(batch) = batch else { + return RenderCommandResult::Failure; + }; + pass.set_vertex_buffer(0, ui_meta.into_inner().vertices.buffer().unwrap().slice(..)); pass.draw(batch.range.clone(), 0..1); RenderCommandResult::Success diff --git a/examples/shader/shader_instancing.rs b/examples/shader/shader_instancing.rs index eee8b51d1c..22149c8dd2 100644 --- a/examples/shader/shader_instancing.rs +++ b/examples/shader/shader_instancing.rs @@ -244,7 +244,7 @@ impl RenderCommand

for DrawMeshInstanced { fn render<'w>( item: &P, _view: (), - instance_buffer: &'w InstanceBuffer, + instance_buffer: Option<&'w InstanceBuffer>, (meshes, render_mesh_instances): SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { @@ -254,6 +254,9 @@ impl RenderCommand

for DrawMeshInstanced { let Some(gpu_mesh) = meshes.into_inner().get(mesh_instance.mesh_asset_id) else { return RenderCommandResult::Failure; }; + let Some(instance_buffer) = instance_buffer else { + return RenderCommandResult::Failure; + }; pass.set_vertex_buffer(0, gpu_mesh.vertex_buffer.slice(..)); pass.set_vertex_buffer(1, instance_buffer.buffer.slice(..));