Skip to content

Commit 81352fc

Browse files
DJMcNabTethysSvensson
authored andcommitted
Squash pr bevyengine#4402
Setup infrastructure for render app owns extract Commit 'progress' Finish API Cleverly avoid needing the param to be 'static This same trick can't work for `StaticSystemParam` fwiw This is because `StaticSystemParam`'s item needs to exactly reference the original param, whereas this just stores it Migrate to the new pattern Remove `spawn_and_forget` It's unused, and was only ever needed for the weird extract logic Fix clippy errors Remove the trick because it's actually stupid Add some docs Fixup docs
1 parent cf831d5 commit 81352fc

24 files changed

Lines changed: 313 additions & 196 deletions

File tree

crates/bevy_core_pipeline/src/lib.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use bevy_render::{
3434
renderer::RenderDevice,
3535
texture::TextureCache,
3636
view::{ExtractedView, Msaa, ViewDepthTexture},
37-
RenderApp, RenderStage, RenderWorld,
37+
Extract, RenderApp, RenderStage,
3838
};
3939

4040
/// When used as a resource, sets the color that is used to clear the screen between frames.
@@ -348,34 +348,36 @@ impl CachedRenderPipelinePhaseItem for Transparent3d {
348348
}
349349

350350
pub fn extract_clear_color(
351-
clear_color: Res<ClearColor>,
352-
clear_colors: Res<RenderTargetClearColors>,
353-
mut render_world: ResMut<RenderWorld>,
351+
mut clear_color: Extract<Res<ClearColor>>,
352+
mut clear_colors: Extract<Res<RenderTargetClearColors>>,
353+
mut commands: Commands,
354354
) {
355+
let clear_color = clear_color.value();
355356
// If the clear color has changed
356357
if clear_color.is_changed() {
357358
// Update the clear color resource in the render world
358-
render_world.insert_resource(clear_color.clone());
359+
commands.insert_resource(clear_color.clone());
359360
}
360361

362+
let clear_colors = clear_colors.value();
361363
// If the clear color has changed
362364
if clear_colors.is_changed() {
363365
// Update the clear color resource in the render world
364-
render_world.insert_resource(clear_colors.clone());
366+
commands.insert_resource(clear_colors.clone());
365367
}
366368
}
367369

368370
pub fn extract_core_pipeline_camera_phases(
369371
mut commands: Commands,
370-
active_2d: Res<ActiveCamera<Camera2d>>,
371-
active_3d: Res<ActiveCamera<Camera3d>>,
372+
mut active_2d: Extract<Res<ActiveCamera<Camera2d>>>,
373+
mut active_3d: Extract<Res<ActiveCamera<Camera3d>>>,
372374
) {
373-
if let Some(entity) = active_2d.get() {
375+
if let Some(entity) = active_2d.value().get() {
374376
commands
375377
.get_or_spawn(entity)
376378
.insert(RenderPhase::<Transparent2d>::default());
377379
}
378-
if let Some(entity) = active_3d.get() {
380+
if let Some(entity) = active_3d.value().get() {
379381
commands.get_or_spawn(entity).insert_bundle((
380382
RenderPhase::<Opaque3d>::default(),
381383
RenderPhase::<AlphaMask3d>::default(),

crates/bevy_ecs/src/event.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Event handling types.
22
3-
use crate::system::{Local, Res, ResMut, SystemParam};
3+
use crate::system::{Local, ReadOnlySystemParamFetch, Res, ResMut, SystemParam};
44
use crate::{self as bevy_ecs, system::Resource};
55
use bevy_utils::tracing::trace;
66
use std::{
@@ -164,6 +164,8 @@ pub struct EventReader<'w, 's, T: Resource> {
164164
events: Res<'w, Events<T>>,
165165
}
166166

167+
unsafe impl<A, T: Resource> ReadOnlySystemParamFetch for EventReaderState<A, T> {}
168+
167169
/// Sends events of type `T`.
168170
#[derive(SystemParam)]
169171
pub struct EventWriter<'w, 's, T: Resource> {

crates/bevy_ecs/src/system/commands/mod.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,6 @@ impl<'w, 's> Commands<'w, 's> {
104104
}
105105
}
106106

107-
/// Spawns a [`Bundle`] without pre-allocating an [`Entity`]. The [`Entity`] will be allocated
108-
/// when this [`Command`] is applied.
109-
pub fn spawn_and_forget(&mut self, bundle: impl Bundle) {
110-
self.queue.push(Spawn { bundle });
111-
}
112-
113107
/// Creates a new entity with the components contained in `bundle`.
114108
///
115109
/// This returns an [`EntityCommands`] builder, which enables inserting more components and

crates/bevy_pbr/src/render/light.rs

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use bevy_render::{
2828
view::{
2929
ExtractedView, ViewUniform, ViewUniformOffset, ViewUniforms, Visibility, VisibleEntities,
3030
},
31+
Extract,
3132
};
3233
use bevy_transform::components::GlobalTransform;
3334
use bevy_utils::{
@@ -331,8 +332,11 @@ pub struct ExtractedClustersPointLights {
331332
data: Vec<VisiblePointLights>,
332333
}
333334

334-
pub fn extract_clusters(mut commands: Commands, views: Query<(Entity, &Clusters), With<Camera>>) {
335-
for (entity, clusters) in views.iter() {
335+
pub fn extract_clusters(
336+
mut commands: Commands,
337+
mut views: Extract<Query<(Entity, &Clusters), With<Camera>>>,
338+
) {
339+
for (entity, clusters) in views.value().iter() {
336340
commands.get_or_spawn(entity).insert_bundle((
337341
ExtractedClustersPointLights {
338342
data: clusters.lights.clone(),
@@ -348,20 +352,25 @@ pub fn extract_clusters(mut commands: Commands, views: Query<(Entity, &Clusters)
348352

349353
pub fn extract_lights(
350354
mut commands: Commands,
351-
ambient_light: Res<AmbientLight>,
352-
point_light_shadow_map: Res<PointLightShadowMap>,
353-
directional_light_shadow_map: Res<DirectionalLightShadowMap>,
354-
global_point_lights: Res<GlobalVisiblePointLights>,
355+
mut ambient_light: Extract<Res<AmbientLight>>,
356+
mut point_light_shadow_map: Extract<Res<PointLightShadowMap>>,
357+
mut directional_light_shadow_map: Extract<Res<DirectionalLightShadowMap>>,
358+
mut global_point_lights: Extract<Res<GlobalVisiblePointLights>>,
355359
// visible_point_lights: Query<&VisiblePointLights>,
356-
mut point_lights: Query<(&PointLight, &mut CubemapVisibleEntities, &GlobalTransform)>,
357-
mut directional_lights: Query<(
358-
Entity,
359-
&DirectionalLight,
360-
&mut VisibleEntities,
361-
&GlobalTransform,
362-
&Visibility,
363-
)>,
360+
mut point_lights: Extract<Query<(&PointLight, &CubemapVisibleEntities, &GlobalTransform)>>,
361+
mut directional_lights: Extract<
362+
Query<(
363+
Entity,
364+
&DirectionalLight,
365+
&VisibleEntities,
366+
&GlobalTransform,
367+
&Visibility,
368+
)>,
369+
>,
364370
) {
371+
let ambient_light = ambient_light.value();
372+
let point_light_shadow_map = point_light_shadow_map.value();
373+
let directional_light_shadow_map = directional_light_shadow_map.value();
365374
commands.insert_resource(ExtractedAmbientLight {
366375
color: ambient_light.color,
367376
brightness: ambient_light.brightness,
@@ -379,11 +388,15 @@ pub fn extract_lights(
379388
// https://catlikecoding.com/unity/tutorials/custom-srp/point-and-spot-shadows/
380389
let point_light_texel_size = 2.0 / point_light_shadow_map.size as f32;
381390

382-
for entity in global_point_lights.iter().copied() {
383-
if let Ok((point_light, cubemap_visible_entities, transform)) = point_lights.get_mut(entity)
384-
{
385-
let render_cubemap_visible_entities =
386-
std::mem::take(cubemap_visible_entities.into_inner());
391+
let point_lights = point_lights.value();
392+
for entity in global_point_lights.value().iter().copied() {
393+
if let Ok((point_light, cubemap_visible_entities, transform)) = point_lights.get(entity) {
394+
// PERF: Ideally, this would avoid creating new allocations each frame.
395+
// The nicest way to do that would be to get last frame's render_cubemap_visible_entities,
396+
// and clone into that buffer.
397+
// TODO: Evaluate whether moving the buffers into a resource at the end of frame
398+
// is more performant.
399+
let render_cubemap_visible_entities = cubemap_visible_entities.clone();
387400
commands.get_or_spawn(entity).insert_bundle((
388401
ExtractedPointLight {
389402
color: point_light.color,
@@ -407,7 +420,7 @@ pub fn extract_lights(
407420
}
408421

409422
for (entity, directional_light, visible_entities, transform, visibility) in
410-
directional_lights.iter_mut()
423+
directional_lights.value().iter()
411424
{
412425
if !visibility.is_visible {
413426
continue;
@@ -425,7 +438,8 @@ pub fn extract_lights(
425438
);
426439
let directional_light_texel_size =
427440
largest_dimension / directional_light_shadow_map.size as f32;
428-
let render_visible_entities = std::mem::take(visible_entities.into_inner());
441+
// See above
442+
let render_visible_entities = visible_entities.clone();
429443
commands.get_or_spawn(entity).insert_bundle((
430444
ExtractedDirectionalLight {
431445
color: directional_light.color,

crates/bevy_pbr/src/render/mesh.rs

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use bevy_render::{
2222
renderer::{RenderDevice, RenderQueue},
2323
texture::{BevyDefault, GpuImage, Image, TextureFormatPixelInfo},
2424
view::{ComputedVisibility, ViewUniform, ViewUniformOffset, ViewUniforms},
25-
RenderApp, RenderStage,
25+
Extract, RenderApp, RenderStage,
2626
};
2727
use bevy_transform::components::GlobalTransform;
2828
use smallvec::SmallVec;
@@ -97,29 +97,35 @@ pub fn extract_meshes(
9797
mut commands: Commands,
9898
mut previous_caster_len: Local<usize>,
9999
mut previous_not_caster_len: Local<usize>,
100-
caster_query: Query<
101-
(
102-
Entity,
103-
&ComputedVisibility,
104-
&GlobalTransform,
105-
&Handle<Mesh>,
106-
Option<&NotShadowReceiver>,
107-
),
108-
Without<NotShadowCaster>,
100+
mut caster_query: Extract<
101+
Query<
102+
(
103+
Entity,
104+
&ComputedVisibility,
105+
&GlobalTransform,
106+
&Handle<Mesh>,
107+
Option<&NotShadowReceiver>,
108+
),
109+
Without<NotShadowCaster>,
110+
>,
109111
>,
110-
not_caster_query: Query<
111-
(
112-
Entity,
113-
&ComputedVisibility,
114-
&GlobalTransform,
115-
&Handle<Mesh>,
116-
Option<&NotShadowReceiver>,
117-
),
118-
With<NotShadowCaster>,
112+
mut not_caster_query: Extract<
113+
Query<
114+
(
115+
Entity,
116+
&ComputedVisibility,
117+
&GlobalTransform,
118+
&Handle<Mesh>,
119+
Option<&NotShadowReceiver>,
120+
),
121+
With<NotShadowCaster>,
122+
>,
119123
>,
120124
) {
121125
let mut caster_values = Vec::with_capacity(*previous_caster_len);
122-
for (entity, computed_visibility, transform, handle, not_receiver) in caster_query.iter() {
126+
for (entity, computed_visibility, transform, handle, not_receiver) in
127+
caster_query.value().iter()
128+
{
123129
if !computed_visibility.is_visible {
124130
continue;
125131
}
@@ -144,7 +150,9 @@ pub fn extract_meshes(
144150
commands.insert_or_spawn_batch(caster_values);
145151

146152
let mut not_caster_values = Vec::with_capacity(*previous_not_caster_len);
147-
for (entity, computed_visibility, transform, mesh, not_receiver) in not_caster_query.iter() {
153+
for (entity, computed_visibility, transform, mesh, not_receiver) in
154+
not_caster_query.value().iter()
155+
{
148156
if !computed_visibility.is_visible {
149157
continue;
150158
}
@@ -216,18 +224,20 @@ impl SkinnedMeshJoints {
216224
}
217225

218226
pub fn extract_skinned_meshes(
219-
query: Query<(Entity, &ComputedVisibility, &SkinnedMesh)>,
220-
inverse_bindposes: Res<Assets<SkinnedMeshInverseBindposes>>,
221-
joint_query: Query<&GlobalTransform>,
227+
mut query: Extract<Query<(Entity, &ComputedVisibility, &SkinnedMesh)>>,
228+
mut inverse_bindposes: Extract<Res<Assets<SkinnedMeshInverseBindposes>>>,
229+
mut joint_query: Extract<Query<&GlobalTransform>>,
222230
mut commands: Commands,
223231
mut previous_len: Local<usize>,
224232
mut previous_joint_len: Local<usize>,
225233
) {
234+
let inverse_bindposes = inverse_bindposes.value();
226235
let mut values = Vec::with_capacity(*previous_len);
227236
let mut joints = Vec::with_capacity(*previous_joint_len);
228237
let mut last_start = 0;
229238

230-
for (entity, computed_visibility, skin) in query.iter() {
239+
let joint_query = joint_query.value();
240+
for (entity, computed_visibility, skin) in query.value().iter() {
231241
if !computed_visibility.is_visible {
232242
continue;
233243
}

crates/bevy_pbr/src/wireframe.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use bevy_asset::{load_internal_asset, Handle, HandleUntyped};
55
use bevy_core_pipeline::Opaque3d;
66
use bevy_ecs::{prelude::*, reflect::ReflectComponent};
77
use bevy_reflect::{Reflect, TypeUuid};
8+
use bevy_render::Extract;
89
use bevy_render::{
910
mesh::{Mesh, MeshVertexBufferLayout},
1011
render_asset::RenderAssets,
@@ -47,14 +48,18 @@ impl Plugin for WireframePlugin {
4748
}
4849
}
4950

50-
fn extract_wireframe_config(mut commands: Commands, wireframe_config: Res<WireframeConfig>) {
51+
fn extract_wireframe_config(
52+
mut commands: Commands,
53+
mut wireframe_config: Extract<Res<WireframeConfig>>,
54+
) {
55+
let wireframe_config = wireframe_config.value();
5156
if wireframe_config.is_added() || wireframe_config.is_changed() {
5257
commands.insert_resource(wireframe_config.into_inner().clone());
5358
}
5459
}
5560

56-
fn extract_wireframes(mut commands: Commands, query: Query<Entity, With<Wireframe>>) {
57-
for entity in query.iter() {
61+
fn extract_wireframes(mut commands: Commands, mut query: Extract<Query<Entity, With<Wireframe>>>) {
62+
for entity in query.value().iter() {
5863
commands.get_or_spawn(entity).insert(Wireframe);
5964
}
6065
}

crates/bevy_render/src/camera/camera.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::{
66
render_asset::RenderAssets,
77
render_resource::TextureView,
88
view::{ExtractedView, ExtractedWindows, VisibleEntities},
9-
RenderApp, RenderStage,
9+
Extract, RenderApp, RenderStage,
1010
};
1111
use bevy_app::{App, CoreStage, Plugin, StartupStage};
1212
use bevy_asset::{AssetEvent, Assets, Handle};
@@ -288,18 +288,22 @@ pub struct ExtractedCamera {
288288

289289
pub fn extract_cameras<M: Component + Default>(
290290
mut commands: Commands,
291-
windows: Res<Windows>,
292-
images: Res<Assets<Image>>,
293-
active_camera: Res<ActiveCamera<M>>,
294-
query: Query<(&Camera, &GlobalTransform, &VisibleEntities), With<M>>,
291+
mut windows: Extract<Res<Windows>>,
292+
mut images: Extract<Res<Assets<Image>>>,
293+
mut active_camera: Extract<Res<ActiveCamera<M>>>,
294+
mut query: Extract<Query<(&Camera, &GlobalTransform, &VisibleEntities), With<M>>>,
295295
) {
296+
let active_camera = active_camera.value();
296297
if let Some(entity) = active_camera.get() {
297-
if let Ok((camera, transform, visible_entities)) = query.get(entity) {
298-
if let Some(size) = camera.target.get_physical_size(&windows, &images) {
298+
if let Ok((camera, transform, visible_entities)) = query.value().get(entity) {
299+
if let Some(size) = camera
300+
.target
301+
.get_physical_size(&windows.value(), &images.value())
302+
{
299303
commands.get_or_spawn(entity).insert_bundle((
300304
ExtractedCamera {
301305
target: camera.target.clone(),
302-
physical_size: camera.target.get_physical_size(&windows, &images),
306+
physical_size: Some(size),
303307
},
304308
ExtractedView {
305309
projection: camera.projection_matrix,

0 commit comments

Comments
 (0)