start making ResourceProvider::update world read-only

This commit is contained in:
Carter Anderson 2020-04-11 13:29:29 -07:00
parent 78d1958090
commit 08abef1c75
9 changed files with 162 additions and 94 deletions

View file

@ -151,6 +151,7 @@ impl AppBuilder {
.add_stage(stage::FIRST)
.add_stage(stage::EVENT_UPDATE)
.add_stage(stage::UPDATE)
.add_stage(stage::POST_UPDATE)
.add_stage(stage::LAST)
}
@ -162,6 +163,14 @@ impl AppBuilder {
self.add_system(system)
}
pub fn build_system_on_stage<F>(&mut self, stage_name: &str, build: F) -> &mut Self
where
F: Fn(&mut Resources) -> Box<dyn Schedulable>,
{
let system = build(self.resources_mut());
self.add_system_to_stage(stage_name, system)
}
pub fn add_system_to_stage(
&mut self,
stage_name: &str,

View file

@ -1,4 +1,7 @@
use bevy_app::{Events, GetEventReader};
use bevy_window::WindowResized;
use glam::Mat4;
use legion::prelude::*;
#[derive(Default)]
pub struct ActiveCamera;
@ -115,4 +118,27 @@ 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| {
// TODO: refactor this to "window_resized_events.latest()"
let primary_window_resized_event = window_resized_events
.iter(&mut window_resized_event_reader)
.rev()
.filter(|event| event.is_primary)
.next();
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,
);
}
}
})
}

View file

@ -83,8 +83,6 @@ impl RenderPlugin {
resources.get_event_reader::<WindowResized>(),
))
.add_resource_provider(LightResourceProvider::new(10))
// TODO: move me to ui crate
// .add_resource_provider(UiResourceProvider::new())
.add_resource_provider(MeshResourceProvider::new())
.add_resource_provider(UniformResourceProvider::<StandardMaterial>::new(true))
.add_resource_provider(UniformResourceProvider::<LocalToWorld>::new(true))
@ -98,7 +96,9 @@ impl AppPlugin for RenderPlugin {
let mut asset_batchers = AssetBatchers::default();
asset_batchers.batch_types2::<Mesh, StandardMaterial>();
app.add_system(build_entity_render_resource_assignments_system())
.add_stage_after(stage::UPDATE, RENDER_STAGE)
.build_system_on_stage(stage::POST_UPDATE, camera::camera_update_system)
.add_system_to_stage(stage::POST_UPDATE, mesh::mesh_batcher_system())
.add_stage_after(stage::POST_UPDATE, RENDER_STAGE)
.add_resource(RenderGraph::default())
.add_resource(AssetStorage::<Mesh>::new())
.add_resource(AssetStorage::<Texture>::new())

View file

@ -1,6 +1,7 @@
use crate::Vertex;
use bevy_asset::Asset;
use crate::{render_resource::AssetBatchers, Vertex, Renderable};
use bevy_asset::{Handle, Asset};
use glam::*;
use legion::prelude::*;
pub enum MeshType {
Cube,
@ -118,3 +119,15 @@ pub fn create_cube() -> (Vec<Vertex>, Vec<u16>) {
pub fn create_plane(size: f32) -> (Vec<Vertex>, Vec<u16>) {
create_quad(vec2(size, size))
}
pub fn mesh_batcher_system() -> Box<dyn Schedulable> {
SystemBuilder::new("mesh_batcher")
.write_resource::<AssetBatchers>()
.with_query(<(Read<Handle<Mesh>>, Read<Renderable>)>::query().filter(changed::<Handle<Mesh>>()))
.build(|_, world, asset_batchers, query| {
for (entity, (mesh_handle, _renderable)) in query.iter_entities(world) {
asset_batchers.set_entity_handle(entity, *mesh_handle);
}
})
}

View file

@ -9,8 +9,12 @@ pub trait ResourceProvider {
_resources: &Resources,
) {
}
// TODO: make this read-only
fn update(&mut self, _render_context: &mut dyn RenderContext, _world: &mut World, _resources: &Resources) {
}
// TODO: remove this
fn finish_update(
&mut self,
_render_context: &mut dyn RenderContext,
@ -18,4 +22,10 @@ pub trait ResourceProvider {
_resources: &Resources,
) {
}
/// Runs after resources have been created on the gpu. In general systems here write gpu-related resources back to entities in this step
fn post_update(&mut self, _render_context: &dyn RenderContext, _world: &mut World, _resources: &Resources) {
}
}

View file

@ -27,31 +27,11 @@ impl Camera2dResourceProvider {
window_resized_event_reader,
}
}
}
impl ResourceProvider for Camera2dResourceProvider {
fn initialize(
fn update_read_only(
&mut self,
render_context: &mut dyn RenderContext,
_world: &mut World,
resources: &Resources,
) {
let buffer = render_context.create_buffer(BufferInfo {
size: std::mem::size_of::<[[f32; 4]; 4]>(),
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
..Default::default()
});
let mut render_resource_assignments =
resources.get_mut::<RenderResourceAssignments>().unwrap();
render_resource_assignments.set(resource_name::uniform::CAMERA2D, buffer);
self.camera_buffer = Some(buffer);
}
fn update(
&mut self,
render_context: &mut dyn RenderContext,
world: &mut World,
world: &World,
resources: &Resources,
) {
let window_resized_events = resources.get::<Events<WindowResized>>().unwrap();
@ -61,14 +41,10 @@ impl ResourceProvider for Camera2dResourceProvider {
.filter(|event| event.is_primary)
.next();
if let Some(primary_window_resized_event) = primary_window_resized_event {
if let Some(_) = primary_window_resized_event {
let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>();
for (mut camera, _) in <(Write<Camera>, Read<ActiveCamera2d>)>::query().iter_mut(world)
for (camera, _) in <(Read<Camera>, Read<ActiveCamera2d>)>::query().iter(world)
{
camera.update(
primary_window_resized_event.width,
primary_window_resized_event.height,
);
let camera_matrix: [[f32; 4]; 4] = camera.view_matrix.to_cols_array_2d();
if let Some(old_tmp_buffer) = self.tmp_buffer {
@ -97,3 +73,32 @@ impl ResourceProvider for Camera2dResourceProvider {
}
}
}
impl ResourceProvider for Camera2dResourceProvider {
fn initialize(
&mut self,
render_context: &mut dyn RenderContext,
_world: &mut World,
resources: &Resources,
) {
let buffer = render_context.create_buffer(BufferInfo {
size: std::mem::size_of::<[[f32; 4]; 4]>(),
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
..Default::default()
});
let mut render_resource_assignments =
resources.get_mut::<RenderResourceAssignments>().unwrap();
render_resource_assignments.set(resource_name::uniform::CAMERA2D, buffer);
self.camera_buffer = Some(buffer);
}
fn update(
&mut self,
render_context: &mut dyn RenderContext,
world: &mut World,
resources: &Resources,
) {
self.update_read_only(render_context, world, resources);
}
}

View file

@ -5,7 +5,8 @@ use crate::{
resource_name, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments,
ResourceProvider,
},
ActiveCamera, Camera, renderer_2::RenderContext,
renderer_2::RenderContext,
ActiveCamera, Camera,
};
use bevy_app::{EventReader, Events};
@ -27,43 +28,19 @@ impl CameraResourceProvider {
window_resized_event_reader,
}
}
}
impl ResourceProvider for CameraResourceProvider {
fn initialize(
&mut self,
render_context: &mut dyn RenderContext,
_world: &mut World,
resources: &Resources,
) {
let buffer = render_context.create_buffer(BufferInfo {
size: std::mem::size_of::<[[f32; 4]; 4]>(),
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
..Default::default()
});
let mut render_resource_assignments =
resources.get_mut::<RenderResourceAssignments>().unwrap();
render_resource_assignments.set(resource_name::uniform::CAMERA, buffer);
self.camera_buffer = Some(buffer);
}
fn update(&mut self, render_context: &mut dyn RenderContext, world: &mut World, resources: &Resources) {
pub fn update_read_only(&mut self, world: &World, resources: &Resources, render_context: &mut dyn RenderContext) {
let window_resized_events = resources.get::<Events<WindowResized>>().unwrap();
let primary_window_resized_event = window_resized_events
.iter(&mut self.window_resized_event_reader)
.rev()
.filter(|event| event.is_primary)
.next();
if let Some(primary_window_resized_event) = primary_window_resized_event {
if let Some(_) = primary_window_resized_event {
let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>();
for (mut camera, local_to_world, _) in
<(Write<Camera>, Read<LocalToWorld>, Read<ActiveCamera>)>::query().iter_mut(world)
for (camera, local_to_world, _) in
<(Read<Camera>, Read<LocalToWorld>, Read<ActiveCamera>)>::query().iter(world)
{
camera.update(
primary_window_resized_event.width,
primary_window_resized_event.height,
);
let camera_matrix: [[f32; 4]; 4] =
(camera.view_matrix * local_to_world.0).to_cols_array_2d();
@ -93,3 +70,32 @@ impl ResourceProvider for CameraResourceProvider {
}
}
}
impl ResourceProvider for CameraResourceProvider {
fn initialize(
&mut self,
render_context: &mut dyn RenderContext,
_world: &mut World,
resources: &Resources,
) {
let buffer = render_context.create_buffer(BufferInfo {
size: std::mem::size_of::<[[f32; 4]; 4]>(),
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
..Default::default()
});
let mut render_resource_assignments =
resources.get_mut::<RenderResourceAssignments>().unwrap();
render_resource_assignments.set(resource_name::uniform::CAMERA, buffer);
self.camera_buffer = Some(buffer);
}
fn update(
&mut self,
render_context: &mut dyn RenderContext,
world: &mut World,
resources: &Resources,
) {
self.update_read_only(world, resources, render_context);
}
}

View file

@ -33,30 +33,7 @@ impl LightResourceProvider {
tmp_count_buffer: None,
}
}
}
impl ResourceProvider for LightResourceProvider {
fn initialize(
&mut self,
render_context: &mut dyn RenderContext,
_world: &mut World,
resources: &Resources,
) {
let light_uniform_size =
std::mem::size_of::<LightCount>() + self.max_lights * std::mem::size_of::<LightRaw>();
let buffer = render_context.create_buffer(BufferInfo {
size: light_uniform_size,
buffer_usage: BufferUsage::UNIFORM | BufferUsage::COPY_SRC | BufferUsage::COPY_DST,
..Default::default()
});
let mut render_resource_assignments =
resources.get_mut::<RenderResourceAssignments>().unwrap();
render_resource_assignments.set(resource_name::uniform::LIGHTS, buffer);
self.light_buffer = Some(buffer);
}
fn update(&mut self, render_context: &mut dyn RenderContext, world: &mut World, _resources: &Resources) {
fn update_read_only(&mut self, render_context: &mut dyn RenderContext, world: &World) {
if self.lights_are_dirty {
let light_query = <(Read<Light>, Read<LocalToWorld>, Read<Translation>)>::query();
let light_count = light_query.iter(world).count();
@ -123,3 +100,29 @@ impl ResourceProvider for LightResourceProvider {
}
}
}
impl ResourceProvider for LightResourceProvider {
fn initialize(
&mut self,
render_context: &mut dyn RenderContext,
_world: &mut World,
resources: &Resources,
) {
let light_uniform_size =
std::mem::size_of::<LightCount>() + self.max_lights * std::mem::size_of::<LightRaw>();
let buffer = render_context.create_buffer(BufferInfo {
size: light_uniform_size,
buffer_usage: BufferUsage::UNIFORM | BufferUsage::COPY_SRC | BufferUsage::COPY_DST,
..Default::default()
});
let mut render_resource_assignments =
resources.get_mut::<RenderResourceAssignments>().unwrap();
render_resource_assignments.set(resource_name::uniform::LIGHTS, buffer);
self.light_buffer = Some(buffer);
}
fn update(&mut self, render_context: &mut dyn RenderContext, world: &mut World, _resources: &Resources) {
self.update_read_only(render_context, world);
}
}

View file

@ -40,7 +40,7 @@ impl MeshResourceProvider {
fn setup_mesh_resources(
render_context: &mut dyn RenderContext,
mesh_storage: &mut AssetStorage<Mesh>,
mesh_storage: &AssetStorage<Mesh>,
handle: Handle<Mesh>,
render_resource_assignments: &mut RenderResourceAssignments,
) {
@ -91,10 +91,6 @@ impl ResourceProvider for MeshResourceProvider {
}
fn update(&mut self, _render_context: &mut dyn RenderContext, world: &mut World, resources: &Resources) {
let mut asset_batchers = resources.get_mut::<AssetBatchers>().unwrap();
for (entity, (mesh_handle, _renderable)) in self.mesh_query.iter_entities_mut(world) {
asset_batchers.set_entity_handle(entity, *mesh_handle);
}
}
fn finish_update(
@ -103,7 +99,7 @@ impl ResourceProvider for MeshResourceProvider {
_world: &mut World,
resources: &Resources,
) {
let mut mesh_storage = resources.get_mut::<AssetStorage<Mesh>>().unwrap();
let mut mesh_storage = resources.get::<AssetStorage<Mesh>>().unwrap();
let mut asset_batchers = resources.get_mut::<AssetBatchers>().unwrap();
// this scope is necessary because the Fetch<AssetBatchers> pointer behaves weirdly
@ -114,7 +110,7 @@ impl ResourceProvider for MeshResourceProvider {
log::trace!("setup mesh for {:?}", batch.render_resource_assignments.id);
Self::setup_mesh_resources(
render_context,
&mut mesh_storage,
&mesh_storage,
handle,
&mut batch.render_resource_assignments,
);