start porting "query" systems from SystemBuilder to functions
This commit is contained in:
parent
83d5275e10
commit
0472cbfc7c
@ -28,7 +28,7 @@ pub mod prelude {
|
||||
entity::Entity,
|
||||
event::Event,
|
||||
filter::filter_fns::*,
|
||||
query::{IntoQuery, Query, Read, Tagged, TryRead, TryWrite, Write},
|
||||
query::{IntoQuery, Query as FilteredQuery, Read, Tagged, TryRead, TryWrite, Write},
|
||||
world::{Universe, World},
|
||||
};
|
||||
}
|
||||
|
||||
@ -270,7 +270,7 @@ pub fn impl_fn_query_systems(_input: TokenStream) -> TokenStream {
|
||||
fn system_id(mut self, id: SystemId) -> Box<dyn Schedulable> {
|
||||
let resource_access: Access<ResourceTypeId> = #resource_access;
|
||||
let component_access: Access<ComponentTypeId> = #component_access;
|
||||
|
||||
|
||||
let run_fn = FuncSystemFnWrapper(
|
||||
move |_command_buffer,
|
||||
_world,
|
||||
|
||||
@ -21,5 +21,7 @@ pub mod prelude {
|
||||
ResMut,
|
||||
System,
|
||||
SystemBuilder,
|
||||
Query,
|
||||
SubWorld
|
||||
};
|
||||
}
|
||||
|
||||
@ -54,106 +54,99 @@ impl SystemNode for LightsNode {
|
||||
let mut tmp_light_buffer = None;
|
||||
let mut command_queue = self.command_queue.clone();
|
||||
let max_lights = self.max_lights;
|
||||
SystemBuilder::new("light_node")
|
||||
.read_resource::<RenderResources>()
|
||||
// TODO: this write on RenderResourceAssignments will prevent this system from running in parallel with other systems that do the same
|
||||
.write_resource::<RenderResourceAssignments>()
|
||||
.with_query(<(Read<Light>, Read<LocalToWorld>, Read<Translation>)>::query())
|
||||
.build(
|
||||
move |_,
|
||||
world,
|
||||
(render_resource_context, ref mut render_resource_assignments),
|
||||
query| {
|
||||
if !lights_are_dirty {
|
||||
return;
|
||||
}
|
||||
(move |world: &mut SubWorld,
|
||||
render_resources: Res<RenderResources>,
|
||||
// TODO: this write on RenderResourceAssignments will prevent this system from running in parallel with other systems that do the same
|
||||
mut render_resource_assignments: ResMut<RenderResourceAssignments>,
|
||||
query: &mut Query<(Read<Light>, Read<LocalToWorld>, Read<Translation>)>| {
|
||||
if !lights_are_dirty {
|
||||
return;
|
||||
}
|
||||
|
||||
let render_resources = &render_resource_context.context;
|
||||
if light_buffer.is_none() {
|
||||
let light_uniform_size = std::mem::size_of::<LightCount>()
|
||||
+ max_lights * std::mem::size_of::<LightRaw>();
|
||||
let render_resources = &render_resources.context;
|
||||
if light_buffer.is_none() {
|
||||
let light_uniform_size = std::mem::size_of::<LightCount>()
|
||||
+ max_lights * std::mem::size_of::<LightRaw>();
|
||||
|
||||
let buffer = render_resources.create_buffer(BufferInfo {
|
||||
size: light_uniform_size,
|
||||
buffer_usage: BufferUsage::UNIFORM
|
||||
| BufferUsage::COPY_SRC
|
||||
| BufferUsage::COPY_DST,
|
||||
..Default::default()
|
||||
});
|
||||
render_resource_assignments.set(
|
||||
resource_name::uniform::LIGHTS,
|
||||
RenderResourceAssignment::Buffer {
|
||||
resource: buffer,
|
||||
range: 0..light_uniform_size as u64,
|
||||
dynamic_index: None,
|
||||
},
|
||||
);
|
||||
light_buffer = Some(buffer);
|
||||
}
|
||||
let buffer = render_resources.create_buffer(BufferInfo {
|
||||
size: light_uniform_size,
|
||||
buffer_usage: BufferUsage::UNIFORM
|
||||
| BufferUsage::COPY_SRC
|
||||
| BufferUsage::COPY_DST,
|
||||
..Default::default()
|
||||
});
|
||||
render_resource_assignments.set(
|
||||
resource_name::uniform::LIGHTS,
|
||||
RenderResourceAssignment::Buffer {
|
||||
resource: buffer,
|
||||
range: 0..light_uniform_size as u64,
|
||||
dynamic_index: None,
|
||||
},
|
||||
);
|
||||
light_buffer = Some(buffer);
|
||||
}
|
||||
|
||||
let light_count = query.iter(world).count();
|
||||
let light_count = query.iter(world).count();
|
||||
|
||||
if light_count == 0 {
|
||||
return;
|
||||
}
|
||||
if light_count == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
lights_are_dirty = false;
|
||||
let size = std::mem::size_of::<LightRaw>();
|
||||
let total_size = size * light_count;
|
||||
let light_count_size = std::mem::size_of::<LightCount>();
|
||||
lights_are_dirty = false;
|
||||
let size = std::mem::size_of::<LightRaw>();
|
||||
let total_size = size * light_count;
|
||||
let light_count_size = std::mem::size_of::<LightCount>();
|
||||
|
||||
if let Some(old_tmp_light_buffer) = tmp_light_buffer {
|
||||
render_resources.remove_buffer(old_tmp_light_buffer);
|
||||
}
|
||||
if let Some(old_tmp_light_buffer) = tmp_light_buffer {
|
||||
render_resources.remove_buffer(old_tmp_light_buffer);
|
||||
}
|
||||
|
||||
if let Some(old_tmp_count_buffer) = tmp_count_buffer {
|
||||
render_resources.remove_buffer(old_tmp_count_buffer);
|
||||
}
|
||||
if let Some(old_tmp_count_buffer) = tmp_count_buffer {
|
||||
render_resources.remove_buffer(old_tmp_count_buffer);
|
||||
}
|
||||
|
||||
tmp_light_buffer = Some(render_resources.create_buffer_mapped(
|
||||
BufferInfo {
|
||||
size: total_size,
|
||||
buffer_usage: BufferUsage::COPY_SRC,
|
||||
..Default::default()
|
||||
},
|
||||
&mut |data, _renderer| {
|
||||
for ((light, local_to_world, translation), slot) in
|
||||
query.iter(world).zip(data.chunks_exact_mut(size))
|
||||
{
|
||||
slot.copy_from_slice(
|
||||
LightRaw::from(&light, &local_to_world.0, &translation)
|
||||
.as_bytes(),
|
||||
);
|
||||
}
|
||||
},
|
||||
));
|
||||
tmp_count_buffer = Some(render_resources.create_buffer_mapped(
|
||||
BufferInfo {
|
||||
size: light_count_size,
|
||||
buffer_usage: BufferUsage::COPY_SRC,
|
||||
..Default::default()
|
||||
},
|
||||
&mut |data, _renderer| {
|
||||
data.copy_from_slice([light_count as u32, 0, 0, 0].as_bytes());
|
||||
},
|
||||
));
|
||||
|
||||
command_queue.copy_buffer_to_buffer(
|
||||
tmp_count_buffer.unwrap(),
|
||||
0,
|
||||
light_buffer.unwrap(),
|
||||
0,
|
||||
light_count_size as u64,
|
||||
);
|
||||
|
||||
command_queue.copy_buffer_to_buffer(
|
||||
tmp_light_buffer.unwrap(),
|
||||
0,
|
||||
light_buffer.unwrap(),
|
||||
light_count_size as u64,
|
||||
total_size as u64,
|
||||
);
|
||||
tmp_light_buffer = Some(render_resources.create_buffer_mapped(
|
||||
BufferInfo {
|
||||
size: total_size,
|
||||
buffer_usage: BufferUsage::COPY_SRC,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
&mut |data, _renderer| {
|
||||
for ((light, local_to_world, translation), slot) in
|
||||
query.iter(world).zip(data.chunks_exact_mut(size))
|
||||
{
|
||||
slot.copy_from_slice(
|
||||
LightRaw::from(&light, &local_to_world.0, &translation).as_bytes(),
|
||||
);
|
||||
}
|
||||
},
|
||||
));
|
||||
tmp_count_buffer = Some(render_resources.create_buffer_mapped(
|
||||
BufferInfo {
|
||||
size: light_count_size,
|
||||
buffer_usage: BufferUsage::COPY_SRC,
|
||||
..Default::default()
|
||||
},
|
||||
&mut |data, _renderer| {
|
||||
data.copy_from_slice([light_count as u32, 0, 0, 0].as_bytes());
|
||||
},
|
||||
));
|
||||
|
||||
command_queue.copy_buffer_to_buffer(
|
||||
tmp_count_buffer.unwrap(),
|
||||
0,
|
||||
light_buffer.unwrap(),
|
||||
0,
|
||||
light_count_size as u64,
|
||||
);
|
||||
|
||||
command_queue.copy_buffer_to_buffer(
|
||||
tmp_light_buffer.unwrap(),
|
||||
0,
|
||||
light_buffer.unwrap(),
|
||||
light_count_size as u64,
|
||||
total_size as u64,
|
||||
);
|
||||
}).system()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
use bevy_app::{Events, GetEventReader};
|
||||
use bevy_window::WindowResized;
|
||||
use bevy_property::{Properties, Property};
|
||||
use bevy_window::WindowResized;
|
||||
use glam::Mat4;
|
||||
use legion::prelude::*;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Default, Properties)]
|
||||
pub struct ActiveCamera;
|
||||
@ -127,19 +127,19 @@ impl Camera {
|
||||
|
||||
pub fn camera_update_system(resources: &mut Resources) -> Box<dyn Schedulable> {
|
||||
let mut window_resized_event_reader = resources.get_event_reader::<WindowResized>();
|
||||
SystemBuilder::new("camera_update")
|
||||
.read_resource::<Events<WindowResized>>()
|
||||
.with_query(<Write<Camera>>::query())
|
||||
.build(move |_, world, window_resized_events, query| {
|
||||
let primary_window_resized_event = window_resized_event_reader
|
||||
.find_latest(&window_resized_events, |event| event.is_primary);
|
||||
if let Some(primary_window_resized_event) = primary_window_resized_event {
|
||||
for mut camera in query.iter_mut(world) {
|
||||
camera.update(
|
||||
primary_window_resized_event.width,
|
||||
primary_window_resized_event.height,
|
||||
);
|
||||
}
|
||||
(move |world: &mut SubWorld,
|
||||
window_resized_events: Res<Events<WindowResized>>,
|
||||
query: &mut Query<Write<Camera>>| {
|
||||
let primary_window_resized_event = window_resized_event_reader
|
||||
.find_latest(&window_resized_events, |event| event.is_primary);
|
||||
if let Some(primary_window_resized_event) = primary_window_resized_event {
|
||||
for mut camera in query.iter_mut(world) {
|
||||
camera.update(
|
||||
primary_window_resized_event.width,
|
||||
primary_window_resized_event.height,
|
||||
);
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
.system()
|
||||
}
|
||||
|
||||
@ -341,93 +341,91 @@ pub fn mesh_resource_provider_system(resources: &mut Resources) -> Box<dyn Sched
|
||||
// TODO: allow pipelines to specialize on vertex_buffer_descriptor and index_format
|
||||
let vertex_buffer_descriptor = Vertex::get_vertex_buffer_descriptor().unwrap();
|
||||
vertex_buffer_descriptors.set(vertex_buffer_descriptor.clone());
|
||||
SystemBuilder::new("mesh_resource_provider")
|
||||
.read_resource::<RenderResources>()
|
||||
.read_resource::<Assets<Mesh>>()
|
||||
.read_resource::<Events<AssetEvent<Mesh>>>()
|
||||
.with_query(<(Read<Handle<Mesh>>, Write<Renderable>)>::query())
|
||||
.build(
|
||||
move |_, world, (render_resources, meshes, mesh_events), query| {
|
||||
let render_resources = &*render_resources.context;
|
||||
let mut changed_meshes = HashSet::new();
|
||||
for event in mesh_event_reader.iter(&mesh_events) {
|
||||
match event {
|
||||
AssetEvent::Created { handle } => {
|
||||
changed_meshes.insert(*handle);
|
||||
}
|
||||
AssetEvent::Modified { handle } => {
|
||||
changed_meshes.insert(*handle);
|
||||
remove_current_mesh_resources(render_resources, *handle);
|
||||
}
|
||||
AssetEvent::Removed { handle } => {
|
||||
remove_current_mesh_resources(render_resources, *handle);
|
||||
// if mesh was modified and removed in the same update, ignore the modification
|
||||
// events are ordered so future modification events are ok
|
||||
changed_meshes.remove(handle);
|
||||
}
|
||||
}
|
||||
(move |world: &mut SubWorld,
|
||||
render_resources: Res<RenderResources>,
|
||||
meshes: Res<Assets<Mesh>>,
|
||||
mesh_events: Res<Events<AssetEvent<Mesh>>>,
|
||||
query: &mut Query<(Read<Handle<Mesh>>, Write<Renderable>)>| {
|
||||
let render_resources = &*render_resources.context;
|
||||
let mut changed_meshes = HashSet::new();
|
||||
for event in mesh_event_reader.iter(&mesh_events) {
|
||||
match event {
|
||||
AssetEvent::Created { handle } => {
|
||||
changed_meshes.insert(*handle);
|
||||
}
|
||||
|
||||
for changed_mesh_handle in changed_meshes.iter() {
|
||||
if let Some(mesh) = meshes.get(changed_mesh_handle) {
|
||||
let vertex_bytes = mesh
|
||||
.get_vertex_buffer_bytes(&vertex_buffer_descriptor)
|
||||
.unwrap();
|
||||
// TODO: use a staging buffer here
|
||||
let vertex_buffer = render_resources.create_buffer_with_data(
|
||||
BufferInfo {
|
||||
buffer_usage: BufferUsage::VERTEX,
|
||||
..Default::default()
|
||||
},
|
||||
&vertex_bytes,
|
||||
);
|
||||
|
||||
let index_bytes = mesh.get_index_buffer_bytes(IndexFormat::Uint16).unwrap();
|
||||
let index_buffer = render_resources.create_buffer_with_data(
|
||||
BufferInfo {
|
||||
buffer_usage: BufferUsage::INDEX,
|
||||
..Default::default()
|
||||
},
|
||||
&index_bytes,
|
||||
);
|
||||
|
||||
render_resources.set_asset_resource(
|
||||
*changed_mesh_handle,
|
||||
vertex_buffer,
|
||||
VERTEX_BUFFER_ASSET_INDEX,
|
||||
);
|
||||
render_resources.set_asset_resource(
|
||||
*changed_mesh_handle,
|
||||
index_buffer,
|
||||
INDEX_BUFFER_ASSET_INDEX,
|
||||
);
|
||||
}
|
||||
AssetEvent::Modified { handle } => {
|
||||
changed_meshes.insert(*handle);
|
||||
remove_current_mesh_resources(render_resources, *handle);
|
||||
}
|
||||
|
||||
// TODO: remove this once batches are pipeline specific and deprecate assigned_meshes draw target
|
||||
for (handle, mut renderable) in query.iter_mut(world) {
|
||||
if let Some(mesh) = meshes.get(&handle) {
|
||||
renderable
|
||||
.render_resource_assignments
|
||||
.pipeline_specialization
|
||||
.primitive_topology = mesh.primitive_topology;
|
||||
}
|
||||
|
||||
if let Some(vertex_buffer) =
|
||||
render_resources.get_asset_resource(*handle, VERTEX_BUFFER_ASSET_INDEX)
|
||||
{
|
||||
let index_buffer =
|
||||
render_resources.get_asset_resource(*handle, INDEX_BUFFER_ASSET_INDEX);
|
||||
|
||||
renderable.render_resource_assignments.set_vertex_buffer(
|
||||
"Vertex",
|
||||
vertex_buffer,
|
||||
index_buffer,
|
||||
);
|
||||
}
|
||||
AssetEvent::Removed { handle } => {
|
||||
remove_current_mesh_resources(render_resources, *handle);
|
||||
// if mesh was modified and removed in the same update, ignore the modification
|
||||
// events are ordered so future modification events are ok
|
||||
changed_meshes.remove(handle);
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
for changed_mesh_handle in changed_meshes.iter() {
|
||||
if let Some(mesh) = meshes.get(changed_mesh_handle) {
|
||||
let vertex_bytes = mesh
|
||||
.get_vertex_buffer_bytes(&vertex_buffer_descriptor)
|
||||
.unwrap();
|
||||
// TODO: use a staging buffer here
|
||||
let vertex_buffer = render_resources.create_buffer_with_data(
|
||||
BufferInfo {
|
||||
buffer_usage: BufferUsage::VERTEX,
|
||||
..Default::default()
|
||||
},
|
||||
&vertex_bytes,
|
||||
);
|
||||
|
||||
let index_bytes = mesh.get_index_buffer_bytes(IndexFormat::Uint16).unwrap();
|
||||
let index_buffer = render_resources.create_buffer_with_data(
|
||||
BufferInfo {
|
||||
buffer_usage: BufferUsage::INDEX,
|
||||
..Default::default()
|
||||
},
|
||||
&index_bytes,
|
||||
);
|
||||
|
||||
render_resources.set_asset_resource(
|
||||
*changed_mesh_handle,
|
||||
vertex_buffer,
|
||||
VERTEX_BUFFER_ASSET_INDEX,
|
||||
);
|
||||
render_resources.set_asset_resource(
|
||||
*changed_mesh_handle,
|
||||
index_buffer,
|
||||
INDEX_BUFFER_ASSET_INDEX,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: remove this once batches are pipeline specific and deprecate assigned_meshes draw target
|
||||
for (handle, mut renderable) in query.iter_mut(world) {
|
||||
if let Some(mesh) = meshes.get(&handle) {
|
||||
renderable
|
||||
.render_resource_assignments
|
||||
.pipeline_specialization
|
||||
.primitive_topology = mesh.primitive_topology;
|
||||
}
|
||||
|
||||
if let Some(vertex_buffer) =
|
||||
render_resources.get_asset_resource(*handle, VERTEX_BUFFER_ASSET_INDEX)
|
||||
{
|
||||
let index_buffer =
|
||||
render_resources.get_asset_resource(*handle, INDEX_BUFFER_ASSET_INDEX);
|
||||
|
||||
renderable.render_resource_assignments.set_vertex_buffer(
|
||||
"Vertex",
|
||||
vertex_buffer,
|
||||
index_buffer,
|
||||
);
|
||||
}
|
||||
}
|
||||
})
|
||||
.system()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -6,6 +6,45 @@ use bevy_render::{
|
||||
};
|
||||
use legion::prelude::*;
|
||||
|
||||
// TODO: replace with system_fn once configurable "archetype access" is sorted out
|
||||
// pub fn render_resource_sets_system(
|
||||
// world: &mut SubWorld,
|
||||
// pipelines: Res<Assets<PipelineDescriptor>>,
|
||||
// pipeline_compiler: Res<PipelineCompiler>,
|
||||
// pipeline_assignments: Res<PipelineAssignments>,
|
||||
// entity_render_resource_assignments: Res<EntityRenderResourceAssignments>,
|
||||
// query: &mut Query<Write<Renderable>>, // gives SubWorld write access to Renderable
|
||||
// ) {
|
||||
// // PERF: consider doing a par-iter over all renderable components so this can be parallelized
|
||||
// for compiled_pipeline_handle in pipeline_compiler.iter_all_compiled_pipelines() {
|
||||
// if let Some(compiled_pipeline_assignments) = pipeline_assignments
|
||||
// .assignments
|
||||
// .get(compiled_pipeline_handle)
|
||||
// {
|
||||
// let compiled_pipeline = pipelines.get(compiled_pipeline_handle).unwrap();
|
||||
// let pipeline_layout = compiled_pipeline.get_layout().unwrap();
|
||||
|
||||
// for assignment_id in compiled_pipeline_assignments.iter() {
|
||||
// let entity = entity_render_resource_assignments
|
||||
// .get(*assignment_id)
|
||||
// .unwrap();
|
||||
// let mut renderable = world.get_component_mut::<Renderable>(*entity).unwrap();
|
||||
// if !renderable.is_visible || renderable.is_instanced {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// for bind_group in pipeline_layout.bind_groups.iter() {
|
||||
// renderable
|
||||
// .render_resource_assignments
|
||||
// .update_render_resource_set_id(bind_group);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
pub fn render_resource_sets_system() -> Box<dyn Schedulable> {
|
||||
SystemBuilder::new("update_render_resource_sets")
|
||||
.read_resource::<Assets<PipelineDescriptor>>()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user