rework surface and swap chain creation to support arbitrary number of surfaces/windows

This commit is contained in:
Carter Anderson 2020-03-30 19:21:12 -07:00
parent 70b4100132
commit 17d4bec08c
13 changed files with 267 additions and 245 deletions

View file

@ -1,4 +1,4 @@
use super::{CreateWindow, Time, WindowCreated, WindowResize, Windows, Event, WindowDescriptor}; use super::{CreateWindow, Time, WindowCreated, WindowResized, Windows, Event, WindowDescriptor};
use crate::app::{plugin::AppPlugin, AppBuilder}; use crate::app::{plugin::AppPlugin, AppBuilder};
use bevy_transform::transform_system_bundle; use bevy_transform::transform_system_bundle;
@ -20,7 +20,7 @@ impl AppPlugin for CorePlugin {
app = app.add_system(transform_system); app = app.add_system(transform_system);
} }
app = app.add_event::<WindowResize>() app = app.add_event::<WindowResized>()
.add_event::<CreateWindow>() .add_event::<CreateWindow>()
.add_event::<WindowCreated>() .add_event::<WindowCreated>()
.add_resource(Windows::default()) .add_resource(Windows::default())

View file

@ -70,7 +70,7 @@ where
self.event_count += 1; self.event_count += 1;
} }
pub fn iter(&self, event_handle: &mut EventHandle<T>) -> impl Iterator<Item = &T> { pub fn iter(&self, event_handle: &mut EventHandle<T>) -> impl DoubleEndedIterator<Item = &T> {
let a_index = self.a_start_event_count - event_handle.last_event_count; let a_index = self.a_start_event_count - event_handle.last_event_count;
let b_index = self.b_start_event_count - event_handle.last_event_count; let b_index = self.b_start_event_count - event_handle.last_event_count;
event_handle.last_event_count = self.event_count; event_handle.last_event_count = self.event_count;

View file

@ -1,10 +1,11 @@
use super::{WindowDescriptor, WindowId}; use super::{WindowDescriptor, WindowId};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct WindowResize { pub struct WindowResized {
pub id: WindowId, pub id: WindowId,
pub width: u32, pub width: u32,
pub height: u32, pub height: u32,
pub is_primary: bool,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]

View file

@ -3,7 +3,7 @@ pub use winit_windows::*;
use crate::prelude::*; use crate::prelude::*;
use super::{CreateWindow, Window, WindowCreated, WindowResize, Windows}; use super::{CreateWindow, Window, WindowCreated, WindowResized, Windows};
use winit::{ use winit::{
event, event,
event::WindowEvent, event::WindowEvent,
@ -15,8 +15,7 @@ pub struct WinitPlugin;
impl AppPlugin for WinitPlugin { impl AppPlugin for WinitPlugin {
fn build(&self, app: AppBuilder) -> AppBuilder { fn build(&self, app: AppBuilder) -> AppBuilder {
app app.add_resource(WinitWindows::default())
.add_resource(WinitWindows::default())
.set_runner(winit_runner) .set_runner(winit_runner)
} }
@ -52,15 +51,20 @@ pub fn winit_runner(mut app: App) {
let winit_windows = app.resources.get_mut::<WinitWindows>().unwrap(); let winit_windows = app.resources.get_mut::<WinitWindows>().unwrap();
let mut windows = app.resources.get_mut::<Windows>().unwrap(); let mut windows = app.resources.get_mut::<Windows>().unwrap();
let window_id = winit_windows.get_window_id(winit_window_id).unwrap(); let window_id = winit_windows.get_window_id(winit_window_id).unwrap();
let is_primary = windows
.get_primary()
.map(|primary_window| primary_window.id == window_id)
.unwrap_or(false);
let mut window = windows.get_mut(window_id).unwrap(); let mut window = windows.get_mut(window_id).unwrap();
window.width = size.width; window.width = size.width;
window.height = size.height; window.height = size.height;
let mut resize_event = app.resources.get_mut::<Event<WindowResize>>().unwrap(); let mut resize_event = app.resources.get_mut::<Event<WindowResized>>().unwrap();
resize_event.send(WindowResize { resize_event.send(WindowResized {
id: window_id, id: window_id,
height: window.height, height: window.height,
width: window.width, width: window.width,
is_primary,
}); });
} }
event::Event::WindowEvent { event, .. } => match event { event::Event::WindowEvent { event, .. } => match event {
@ -102,22 +106,8 @@ fn handle_create_window_events(
let mut window_created_events = resources.get_mut::<Event<WindowCreated>>().unwrap(); let mut window_created_events = resources.get_mut::<Event<WindowCreated>>().unwrap();
for create_window_event in create_window_events.iter(create_window_event_handle) { for create_window_event in create_window_events.iter(create_window_event_handle) {
let window = Window::new(&create_window_event.descriptor); let window = Window::new(&create_window_event.descriptor);
create_window( winit_windows.create_window(event_loop, &window);
&event_loop, window_created_events.send(WindowCreated { id: window.id });
&mut window_created_events,
&mut winit_windows,
&window,
);
windows.add(window); windows.add(window);
} }
} }
pub fn create_window(
event_loop: &EventLoopWindowTarget<()>,
window_created_events: &mut Event<WindowCreated>,
winit_windows: &mut WinitWindows,
window: &Window,
) {
winit_windows.create_window(event_loop, &window);
window_created_events.send(WindowCreated { id: window.id });
}

View file

@ -14,14 +14,7 @@ use super::{
AssetBatchers, EntityRenderResourceAssignments, RenderResourceAssignments, AssetBatchers, EntityRenderResourceAssignments, RenderResourceAssignments,
}, },
}; };
use crate::{ use crate::{core::WindowResized, prelude::*};
app::{plugin::AppPlugin, AppBuilder},
asset::AssetStorage,
prelude::{
LocalToWorld, Mesh, PipelineDescriptor, Shader, StandardMaterial, Texture,
UniformResourceProvider,
},
};
#[derive(Default)] #[derive(Default)]
pub struct RenderPlugin; pub struct RenderPlugin;
@ -40,8 +33,12 @@ impl RenderPlugin {
.add_draw_target(AssignedBatchesDrawTarget::default()) .add_draw_target(AssignedBatchesDrawTarget::default())
.add_draw_target(AssignedMeshesDrawTarget::default()) .add_draw_target(AssignedMeshesDrawTarget::default())
.add_draw_target(UiDrawTarget::default()) .add_draw_target(UiDrawTarget::default())
.add_resource_provider(CameraResourceProvider::default()) .add_resource_provider(CameraResourceProvider::new(
.add_resource_provider(Camera2dResourceProvider::default()) app.resources.get_event_handle::<WindowResized>(),
))
.add_resource_provider(Camera2dResourceProvider::new(
app.resources.get_event_handle::<WindowResized>(),
))
.add_resource_provider(LightResourceProvider::new(10)) .add_resource_provider(LightResourceProvider::new(10))
.add_resource_provider(UiResourceProvider::new()) .add_resource_provider(UiResourceProvider::new())
.add_resource_provider(MeshResourceProvider::new()) .add_resource_provider(MeshResourceProvider::new())

View file

@ -18,13 +18,4 @@ pub trait ResourceProvider {
_resources: &Resources, _resources: &Resources,
) { ) {
} }
fn resize(
&mut self,
_renderer: &mut dyn Renderer,
_world: &mut World,
_resources: &Resources,
_width: u32,
_height: u32,
) {
}
} }

View file

@ -1,18 +1,29 @@
use crate::render::{ use crate::{
core::WindowResized,
prelude::*,
render::{
render_resource::{ render_resource::{
resource_name, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments, ResourceProvider,
ResourceProvider,
}, },
renderer::Renderer, renderer::Renderer,
ActiveCamera2d, Camera, },
}; };
use legion::prelude::*;
use zerocopy::AsBytes; use zerocopy::AsBytes;
#[derive(Default)]
pub struct Camera2dResourceProvider { pub struct Camera2dResourceProvider {
pub camera_buffer: Option<RenderResource>, pub camera_buffer: Option<RenderResource>,
pub tmp_buffer: Option<RenderResource>, pub tmp_buffer: Option<RenderResource>,
pub window_resized_event_handle: EventHandle<WindowResized>,
}
impl Camera2dResourceProvider {
pub fn new(window_resized_event_handle: EventHandle<WindowResized>) -> Self {
Camera2dResourceProvider {
camera_buffer: None,
tmp_buffer: None,
window_resized_event_handle,
}
}
} }
impl ResourceProvider for Camera2dResourceProvider { impl ResourceProvider for Camera2dResourceProvider {
@ -34,17 +45,22 @@ impl ResourceProvider for Camera2dResourceProvider {
self.camera_buffer = Some(buffer); self.camera_buffer = Some(buffer);
} }
fn resize( fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, resources: &Resources) {
&mut self, let window_resized_events = resources.get::<Event<WindowResized>>().unwrap();
renderer: &mut dyn Renderer, let primary_window_resized_event = window_resized_events
world: &mut World, .iter(&mut self.window_resized_event_handle)
_resources: &Resources, .rev()
width: u32, .filter(|event| event.is_primary)
height: u32, .next();
) {
if let Some(primary_window_resized_event) = primary_window_resized_event {
let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>(); let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>();
for (mut camera, _) in <(Write<Camera>, Read<ActiveCamera2d>)>::query().iter_mut(world) { for (mut camera, _) in <(Write<Camera>, Read<ActiveCamera2d>)>::query().iter_mut(world)
camera.update(width, height); {
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(); let camera_matrix: [[f32; 4]; 4] = camera.view_matrix.to_cols_array_2d();
if let Some(old_tmp_buffer) = self.tmp_buffer { if let Some(old_tmp_buffer) = self.tmp_buffer {
@ -71,4 +87,5 @@ impl ResourceProvider for Camera2dResourceProvider {
); );
} }
} }
}
} }

View file

@ -1,19 +1,31 @@
use crate::render::{ use crate::{
core::WindowResized,
prelude::*,
render::{
render_resource::{ render_resource::{
resource_name, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments, resource_name, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments,
ResourceProvider, ResourceProvider,
}, },
renderer::Renderer, renderer::Renderer,
ActiveCamera, Camera, ActiveCamera, Camera,
},
}; };
use bevy_transform::prelude::LocalToWorld;
use legion::prelude::*;
use zerocopy::AsBytes; use zerocopy::AsBytes;
#[derive(Default)]
pub struct CameraResourceProvider { pub struct CameraResourceProvider {
pub camera_buffer: Option<RenderResource>, pub camera_buffer: Option<RenderResource>,
pub tmp_buffer: Option<RenderResource>, pub tmp_buffer: Option<RenderResource>,
pub window_resized_event_handle: EventHandle<WindowResized>,
}
impl CameraResourceProvider {
pub fn new(window_resized_event_handle: EventHandle<WindowResized>) -> Self {
CameraResourceProvider {
camera_buffer: None,
tmp_buffer: None,
window_resized_event_handle,
}
}
} }
impl ResourceProvider for CameraResourceProvider { impl ResourceProvider for CameraResourceProvider {
@ -35,19 +47,22 @@ impl ResourceProvider for CameraResourceProvider {
self.camera_buffer = Some(buffer); self.camera_buffer = Some(buffer);
} }
fn resize( fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, resources: &Resources) {
&mut self, let window_resized_events = resources.get::<Event<WindowResized>>().unwrap();
renderer: &mut dyn Renderer, let primary_window_resized_event = window_resized_events
world: &mut World, .iter(&mut self.window_resized_event_handle)
_resources: &Resources, .rev()
width: u32, .filter(|event| event.is_primary)
height: u32, .next();
) { if let Some(primary_window_resized_event) = primary_window_resized_event {
let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>(); let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>();
for (mut camera, local_to_world, _) in for (mut camera, local_to_world, _) in
<(Write<Camera>, Read<LocalToWorld>, Read<ActiveCamera>)>::query().iter_mut(world) <(Write<Camera>, Read<LocalToWorld>, Read<ActiveCamera>)>::query().iter_mut(world)
{ {
camera.update(width, height); camera.update(
primary_window_resized_event.width,
primary_window_resized_event.height,
);
let camera_matrix: [[f32; 4]; 4] = let camera_matrix: [[f32; 4]; 4] =
(camera.view_matrix * local_to_world.0).to_cols_array_2d(); (camera.view_matrix * local_to_world.0).to_cols_array_2d();
@ -75,4 +90,5 @@ impl ResourceProvider for CameraResourceProvider {
); );
} }
} }
}
} }

View file

@ -12,6 +12,8 @@ use legion::prelude::Resources;
pub struct FrameTextureResourceProvider { pub struct FrameTextureResourceProvider {
pub name: String, pub name: String,
pub descriptor: TextureDescriptor, pub descriptor: TextureDescriptor,
pub width: u32,
pub height: u32,
} }
impl FrameTextureResourceProvider { impl FrameTextureResourceProvider {
@ -19,12 +21,18 @@ impl FrameTextureResourceProvider {
FrameTextureResourceProvider { FrameTextureResourceProvider {
name: name.to_string(), name: name.to_string(),
descriptor, descriptor,
width: 0,
height: 0,
} }
} }
pub fn update(&mut self, renderer: &mut dyn Renderer, _world: &World, resources: &Resources) { pub fn update(&mut self, renderer: &mut dyn Renderer, resources: &Resources) {
let windows = resources.get::<Windows>().unwrap(); let windows = resources.get::<Windows>().unwrap();
let window = windows.get_primary().unwrap(); let window = windows.get_primary().unwrap();
if self.descriptor.size.width != window.width
|| self.descriptor.size.height != window.height
{
self.descriptor.size.width = window.width; self.descriptor.size.width = window.width;
self.descriptor.size.height = window.height; self.descriptor.size.height = window.height;
@ -37,26 +45,11 @@ impl FrameTextureResourceProvider {
let texture_resource = renderer.create_texture(&self.descriptor, None); let texture_resource = renderer.create_texture(&self.descriptor, None);
render_resource_assignments.set(&self.name, texture_resource); render_resource_assignments.set(&self.name, texture_resource);
} }
}
} }
impl ResourceProvider for FrameTextureResourceProvider { impl ResourceProvider for FrameTextureResourceProvider {
fn initialize( fn update(&mut self, renderer: &mut dyn Renderer, _world: &mut World, resources: &Resources) {
&mut self, self.update(renderer, resources)
renderer: &mut dyn Renderer,
world: &mut World,
resources: &Resources,
) {
self.update(renderer, world, resources);
}
fn resize(
&mut self,
renderer: &mut dyn Renderer,
world: &mut World,
resources: &Resources,
_width: u32,
_height: u32,
) {
self.update(renderer, world, resources);
} }
} }

View file

@ -11,7 +11,6 @@ use crate::{
use std::ops::Range; use std::ops::Range;
pub trait Renderer { pub trait Renderer {
fn resize(&mut self, world: &mut World, resources: &mut Resources);
fn update(&mut self, world: &mut World, resources: &mut Resources); fn update(&mut self, world: &mut World, resources: &mut Resources);
fn create_buffer_with_data(&mut self, buffer_info: BufferInfo, data: &[u8]) -> RenderResource; fn create_buffer_with_data(&mut self, buffer_info: BufferInfo, data: &[u8]) -> RenderResource;
fn create_sampler(&mut self, sampler_descriptor: &SamplerDescriptor) -> RenderResource; fn create_sampler(&mut self, sampler_descriptor: &SamplerDescriptor) -> RenderResource;

View file

@ -8,8 +8,8 @@ pub use wgpu_renderer::*;
pub use wgpu_resources::*; pub use wgpu_resources::*;
use crate::{ use crate::{
app::{plugin::AppPlugin, AppBuilder, system_stage}, app::{plugin::AppPlugin, system_stage, AppBuilder},
core::{Event, WindowResize}, core::{Event, WindowCreated, WindowResized},
render::renderer::Renderer, render::renderer::Renderer,
}; };
@ -29,8 +29,12 @@ impl AppPlugin for WgpuRendererPlugin {
} }
pub fn wgpu_render_system(resources: &Resources) -> impl FnMut(&mut World, &mut Resources) { pub fn wgpu_render_system(resources: &Resources) -> impl FnMut(&mut World, &mut Resources) {
let window_resize_event = resources.get::<Event<WindowResize>>().unwrap(); let window_resized_event = resources.get::<Event<WindowResized>>().unwrap();
let mut wgpu_renderer = futures::executor::block_on(WgpuRenderer::new(window_resize_event.get_handle())); let window_created_event = resources.get::<Event<WindowCreated>>().unwrap();
let mut wgpu_renderer = futures::executor::block_on(WgpuRenderer::new(
window_resized_event.get_handle(),
window_created_event.get_handle(),
));
move |world, resources| { move |world, resources| {
wgpu_renderer.update(world, resources); wgpu_renderer.update(world, resources);
} }

View file

@ -1,7 +1,7 @@
use super::{wgpu_type_converter::OwnedWgpuVertexBufferDescriptor, WgpuRenderPass, WgpuResources}; use super::{wgpu_type_converter::OwnedWgpuVertexBufferDescriptor, WgpuRenderPass, WgpuResources};
use crate::{ use crate::{
asset::{AssetStorage, Handle}, asset::{AssetStorage, Handle},
core::{Event, EventHandle, WindowResize, winit::WinitWindows, Windows}, core::{winit::WinitWindows, Event, EventHandle, WindowCreated, WindowResized, Windows, Window},
legion::prelude::*, legion::prelude::*,
render::{ render::{
pass::{ pass::{
@ -19,21 +19,29 @@ use crate::{
texture::{SamplerDescriptor, TextureDescriptor}, texture::{SamplerDescriptor, TextureDescriptor},
}, },
}; };
use std::{cell::RefCell, collections::HashMap, ops::Deref, rc::Rc}; use std::{
cell::RefCell,
collections::{HashMap, HashSet},
ops::Deref,
rc::Rc,
};
pub struct WgpuRenderer { pub struct WgpuRenderer {
pub device: Rc<RefCell<wgpu::Device>>, pub device: Rc<RefCell<wgpu::Device>>,
pub queue: wgpu::Queue, pub queue: wgpu::Queue,
pub surface: Option<wgpu::Surface>,
pub encoder: Option<wgpu::CommandEncoder>, pub encoder: Option<wgpu::CommandEncoder>,
pub render_pipelines: HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>, pub render_pipelines: HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>,
pub wgpu_resources: WgpuResources, pub wgpu_resources: WgpuResources,
pub window_resize_handle: EventHandle<WindowResize>, pub window_resized_event_handle: EventHandle<WindowResized>,
pub window_created_event_handle: EventHandle<WindowCreated>,
pub intialized: bool, pub intialized: bool,
} }
impl WgpuRenderer { impl WgpuRenderer {
pub async fn new(window_resize_event: EventHandle<WindowResize>) -> Self { pub async fn new(
window_resized_event_handle: EventHandle<WindowResized>,
window_created_event_handle: EventHandle<WindowCreated>,
) -> Self {
let adapter = wgpu::Adapter::request( let adapter = wgpu::Adapter::request(
&wgpu::RequestAdapterOptions { &wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::Default, power_preference: wgpu::PowerPreference::Default,
@ -43,19 +51,21 @@ impl WgpuRenderer {
.await .await
.unwrap(); .unwrap();
let (device, queue) = adapter.request_device(&wgpu::DeviceDescriptor { let (device, queue) = adapter
.request_device(&wgpu::DeviceDescriptor {
extensions: wgpu::Extensions { extensions: wgpu::Extensions {
anisotropic_filtering: false, anisotropic_filtering: false,
}, },
limits: wgpu::Limits::default(), limits: wgpu::Limits::default(),
}).await; })
.await;
WgpuRenderer { WgpuRenderer {
device: Rc::new(RefCell::new(device)), device: Rc::new(RefCell::new(device)),
queue, queue,
surface: None,
encoder: None, encoder: None,
window_resize_handle: window_resize_event, window_resized_event_handle: window_resized_event_handle,
window_created_event_handle,
intialized: false, intialized: false,
wgpu_resources: WgpuResources::default(), wgpu_resources: WgpuResources::default(),
render_pipelines: HashMap::new(), render_pipelines: HashMap::new(),
@ -67,10 +77,7 @@ impl WgpuRenderer {
return; return;
} }
self.create_surface(resources);
self.initialize_resource_providers(world, resources); self.initialize_resource_providers(world, resources);
self.resize(world, resources);
self.intialized = true; self.intialized = true;
} }
@ -342,75 +349,76 @@ impl WgpuRenderer {
} }
} }
pub fn create_surface(&mut self, resources: &Resources) { pub fn handle_window_resized_events(&mut self, resources: &mut Resources) {
let windows = resources.get::<Windows>().unwrap();
let window_resized_events = resources.get::<Event<WindowResized>>().unwrap();
let mut handled_windows = HashSet::new();
// iterate in reverse order so we can handle the latest window resize event first for each window.
// we skip earlier events for the same window because it results in redundant work
for window_resized_event in window_resized_events
.iter(&mut self.window_resized_event_handle)
.rev()
{
if handled_windows.contains(&window_resized_event.id) {
continue;
}
let window = windows
.get(window_resized_event.id)
.expect("Received window resized event for non-existent window");
self.setup_swap_chain(window);
handled_windows.insert(window_resized_event.id);
}
}
pub fn handle_window_created_events(&mut self, resources: &mut Resources) {
let windows = resources.get::<Windows>().unwrap();
let winit_windows = resources.get::<WinitWindows>().unwrap();
let window_created_events = resources.get::<Event<WindowCreated>>().unwrap();
for window_created_event in
window_created_events.iter(&mut self.window_created_event_handle)
{
let window = windows
.get(window_created_event.id)
.expect("Received window created event for non-existent window");
#[cfg(feature = "winit")] #[cfg(feature = "winit")]
{ {
let winit_windows = resources.get::<WinitWindows>().unwrap(); let primary_winit_window = winit_windows.get_window(window.id).unwrap();
let windows = resources.get::<Windows>().unwrap();
let primary_window = windows.get_primary().unwrap();
let primary_winit_window = winit_windows.get_window(primary_window.id).unwrap();
let surface = wgpu::Surface::create(primary_winit_window.deref()); let surface = wgpu::Surface::create(primary_winit_window.deref());
self.surface = Some(surface); self.wgpu_resources
.window_surfaces
.insert(window.id, surface);
self.setup_swap_chain(window);
}
} }
} }
}
impl Renderer for WgpuRenderer { fn setup_swap_chain(&mut self, window: &Window) {
fn resize(&mut self, world: &mut World, resources: &mut Resources) { let surface = self
if let Some(surface) = self.surface.as_ref() { .wgpu_resources
self.encoder = Some( .window_surfaces
self.device .get(&window.id)
.borrow() .expect("Received window resized event for window without a wgpu surface");
.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }),
);
let swap_chain_descriptor: wgpu::SwapChainDescriptor = {
let windows = resources.get::<Windows>().unwrap();
let window = windows.get_primary().unwrap();
window.into()
};
let swap_chain_descriptor: wgpu::SwapChainDescriptor = window.into();
let swap_chain = self let swap_chain = self
.device .device
.borrow() .borrow()
.create_swap_chain(surface, &swap_chain_descriptor); .create_swap_chain(surface, &swap_chain_descriptor);
self.wgpu_resources
// WgpuRenderer can't own swap_chain without creating lifetime ergonomics issues, so lets just store it in World. .window_swap_chains
resources.insert(swap_chain); .insert(window.id, swap_chain);
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
for resource_provider in render_graph.resource_providers.iter_mut() {
resource_provider.resize(
self,
world,
resources,
swap_chain_descriptor.width,
swap_chain_descriptor.height,
);
}
// consume current encoder
let command_buffer = self.encoder.take().unwrap().finish();
self.queue.submit(&[command_buffer]);
} else {
// TODO: remove this warning if this case is not a problem
println!("warning: attempted to resize renderer before surface was ready");
}
} }
}
impl Renderer for WgpuRenderer {
fn update(&mut self, world: &mut World, resources: &mut Resources) { fn update(&mut self, world: &mut World, resources: &mut Resources) {
self.initialize(world, resources); self.initialize(world, resources);
self.handle_window_created_events(resources);
self.handle_window_resized_events(resources);
let resized =
resources
.get::<Event<WindowResize>>()
.unwrap()
.iter(&mut self.window_resize_handle)
.last()
.map(|_| ())
.is_some();
if resized {
self.resize(world, resources);
}
// TODO: this self.encoder handoff is a bit gross, but its here to give resource providers access to buffer copies without // TODO: this self.encoder handoff is a bit gross, but its here to give resource providers access to buffer copies without
// exposing the wgpu renderer internals to ResourceProvider traits. if this can be made cleaner that would be pretty cool. // exposing the wgpu renderer internals to ResourceProvider traits. if this can be made cleaner that would be pretty cool.
self.encoder = Some( self.encoder = Some(
@ -425,13 +433,17 @@ impl Renderer for WgpuRenderer {
let mut encoder = self.encoder.take().unwrap(); let mut encoder = self.encoder.take().unwrap();
let mut swap_chain = resources.get_mut::<wgpu::SwapChain>().unwrap(); // TODO: create swap chain outputs for every swap chain
let swap_chain = self
.wgpu_resources
.window_swap_chains
.values_mut()
.next()
.unwrap();
let frame = swap_chain let frame = swap_chain
.get_next_texture() .get_next_texture()
.expect("Timeout when acquiring next swap chain texture"); .expect("Timeout when acquiring next swap chain texture");
// self.setup_dynamic_entity_shader_uniforms(world, render_graph, &mut encoder);
// setup, pipelines, bind groups, and resources // setup, pipelines, bind groups, and resources
let mut pipeline_storage = resources let mut pipeline_storage = resources
.get_mut::<AssetStorage<PipelineDescriptor>>() .get_mut::<AssetStorage<PipelineDescriptor>>()

View file

@ -10,7 +10,7 @@ use crate::{
}, },
renderer::Renderer, renderer::Renderer,
texture::{SamplerDescriptor, TextureDescriptor}, texture::{SamplerDescriptor, TextureDescriptor},
}, }, core::WindowId,
}; };
use std::collections::HashMap; use std::collections::HashMap;
@ -22,6 +22,8 @@ pub struct WgpuBindGroupInfo {
#[derive(Default)] #[derive(Default)]
pub struct WgpuResources { pub struct WgpuResources {
pub render_resources: RenderResources, pub render_resources: RenderResources,
pub window_surfaces: HashMap<WindowId, wgpu::Surface>,
pub window_swap_chains: HashMap<WindowId, wgpu::SwapChain>,
pub buffers: HashMap<RenderResource, wgpu::Buffer>, pub buffers: HashMap<RenderResource, wgpu::Buffer>,
pub textures: HashMap<RenderResource, wgpu::TextureView>, pub textures: HashMap<RenderResource, wgpu::TextureView>,
pub samplers: HashMap<RenderResource, wgpu::Sampler>, pub samplers: HashMap<RenderResource, wgpu::Sampler>,