From 8a759d3b18b84a2b9220a971ea1c272821852778 Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Mon, 30 Mar 2020 22:23:48 -0700 Subject: [PATCH] begin work on supporting multiple swap chains --- src/core/window/events.rs | 1 + src/core/window/mod.rs | 6 + src/core/window/winit/mod.rs | 4 +- .../renderers/wgpu_renderer/wgpu_renderer.rs | 157 +++++++++++------- 4 files changed, 107 insertions(+), 61 deletions(-) diff --git a/src/core/window/events.rs b/src/core/window/events.rs index a5c2a3b785..a417053a20 100644 --- a/src/core/window/events.rs +++ b/src/core/window/events.rs @@ -16,4 +16,5 @@ pub struct CreateWindow { #[derive(Debug, Clone)] pub struct WindowCreated { pub id: WindowId, + pub is_primary: bool, } diff --git a/src/core/window/mod.rs b/src/core/window/mod.rs index 1a6423428e..7e7acfcfec 100644 --- a/src/core/window/mod.rs +++ b/src/core/window/mod.rs @@ -11,6 +11,12 @@ use uuid::Uuid; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub struct WindowId(Uuid); +impl WindowId { + pub fn to_string(&self) -> String { + self.0.to_simple().to_string() + } +} + pub struct Window { pub id: WindowId, pub width: u32, diff --git a/src/core/window/winit/mod.rs b/src/core/window/winit/mod.rs index 88cae9f8b6..708b3111a9 100644 --- a/src/core/window/winit/mod.rs +++ b/src/core/window/winit/mod.rs @@ -107,7 +107,9 @@ fn handle_create_window_events( for create_window_event in create_window_events.iter(create_window_event_handle) { let window = Window::new(&create_window_event.descriptor); winit_windows.create_window(event_loop, &window); - window_created_events.send(WindowCreated { id: window.id }); + let window_id = window.id; windows.add(window); + let is_primary = windows.get_primary().map(|primary| primary.id == window_id).unwrap_or(false); + window_created_events.send(WindowCreated { id: window_id, is_primary }); } } diff --git a/src/render/renderer/renderers/wgpu_renderer/wgpu_renderer.rs b/src/render/renderer/renderers/wgpu_renderer/wgpu_renderer.rs index 0c5ea80e21..6d7659fea9 100644 --- a/src/render/renderer/renderers/wgpu_renderer/wgpu_renderer.rs +++ b/src/render/renderer/renderers/wgpu_renderer/wgpu_renderer.rs @@ -221,7 +221,8 @@ impl WgpuRenderer { pass_descriptor: &PassDescriptor, global_render_resource_assignments: &RenderResourceAssignments, encoder: &'a mut wgpu::CommandEncoder, - frame: &'a wgpu::SwapChainOutput, + primary_swap_chain: &Option, + swap_chain_outputs: &'a HashMap, ) -> wgpu::RenderPass<'a> { encoder.begin_render_pass(&wgpu::RenderPassDescriptor { color_attachments: &pass_descriptor @@ -232,7 +233,8 @@ impl WgpuRenderer { wgpu_resources, global_render_resource_assignments, c, - frame, + primary_swap_chain, + swap_chain_outputs, ) }) .collect::>(), @@ -241,46 +243,69 @@ impl WgpuRenderer { wgpu_resources, global_render_resource_assignments, d, - frame, + primary_swap_chain, + swap_chain_outputs, ) }), }) } + fn get_texture_view<'a>( + wgpu_resources: &'a WgpuResources, + global_render_resource_assignments: &RenderResourceAssignments, + primary_swap_chain: &Option, + swap_chain_outputs: &'a HashMap, + name: &str, + ) -> &'a wgpu::TextureView { + match name { + resource_name::texture::SWAP_CHAIN => { + if let Some(primary_swap_chain) = primary_swap_chain { + swap_chain_outputs + .get(primary_swap_chain) + .map(|output| &output.view) + .unwrap() + } else { + panic!("No primary swap chain found for color attachment"); + } + } + _ => match global_render_resource_assignments.get(name) { + Some(resource) => wgpu_resources.textures.get(&resource).unwrap(), + None => if let Some(swap_chain_output) = swap_chain_outputs.get(name) { + &swap_chain_output.view + } else { + panic!("Color attachment {} does not exist", name); + } + }, + } + } + fn create_wgpu_color_attachment_descriptor<'a>( wgpu_resources: &'a WgpuResources, global_render_resource_assignments: &RenderResourceAssignments, color_attachment_descriptor: &RenderPassColorAttachmentDescriptor, - frame: &'a wgpu::SwapChainOutput, + primary_swap_chain: &Option, + swap_chain_outputs: &'a HashMap, ) -> wgpu::RenderPassColorAttachmentDescriptor<'a> { - let attachment = match color_attachment_descriptor.attachment.as_str() { - resource_name::texture::SWAP_CHAIN => &frame.view, - _ => { - match global_render_resource_assignments - .get(&color_attachment_descriptor.attachment) - { - Some(resource) => wgpu_resources.textures.get(&resource).unwrap(), - None => panic!( - "Color attachment {} does not exist", - &color_attachment_descriptor.attachment - ), - } - } - }; + let attachment = Self::get_texture_view( + wgpu_resources, + global_render_resource_assignments, + primary_swap_chain, + swap_chain_outputs, + color_attachment_descriptor.attachment.as_str(), + ); - let resolve_target = match color_attachment_descriptor.resolve_target { - Some(ref target) => match target.as_str() { - resource_name::texture::SWAP_CHAIN => Some(&frame.view), - _ => match global_render_resource_assignments.get(target.as_str()) { - Some(resource) => Some(wgpu_resources.textures.get(&resource).unwrap()), - None => panic!( - "Color attachment {} does not exist", - &color_attachment_descriptor.attachment - ), - }, - }, - None => None, - }; + let resolve_target = color_attachment_descriptor + .resolve_target + .as_ref() + .map(|target| { + Self::get_texture_view( + wgpu_resources, + global_render_resource_assignments, + primary_swap_chain, + swap_chain_outputs, + target.as_str(), + ) + }); wgpu::RenderPassColorAttachmentDescriptor { store_op: color_attachment_descriptor.store_op.into(), @@ -295,22 +320,16 @@ impl WgpuRenderer { wgpu_resources: &'a WgpuResources, global_render_resource_assignments: &RenderResourceAssignments, depth_stencil_attachment_descriptor: &RenderPassDepthStencilAttachmentDescriptor, - frame: &'a wgpu::SwapChainOutput, + primary_swap_chain: &Option, + swap_chain_outputs: &'a HashMap, ) -> wgpu::RenderPassDepthStencilAttachmentDescriptor<'a> { - let attachment = match depth_stencil_attachment_descriptor.attachment.as_str() { - resource_name::texture::SWAP_CHAIN => &frame.view, - _ => { - match global_render_resource_assignments - .get(&depth_stencil_attachment_descriptor.attachment) - { - Some(ref resource) => wgpu_resources.textures.get(&resource).unwrap(), - None => panic!( - "Depth stencil attachment {} does not exist", - &depth_stencil_attachment_descriptor.attachment - ), - } - } - }; + let attachment = Self::get_texture_view( + wgpu_resources, + global_render_resource_assignments, + primary_swap_chain, + swap_chain_outputs, + depth_stencil_attachment_descriptor.attachment.as_str(), + ); wgpu::RenderPassDepthStencilAttachmentDescriptor { attachment, @@ -422,6 +441,33 @@ impl WgpuRenderer { .window_swap_chains .insert(window.id, swap_chain); } + + fn get_swap_chain_outputs( + &mut self, + resources: &Resources, + ) -> (Option, HashMap) { + let primary_window_id = resources + .get::() + .unwrap() + .get_primary() + .map(|window| window.id); + let primary_swap_chain = + primary_window_id.map(|primary_window_id| primary_window_id.to_string()); + let swap_chain_outputs = self + .wgpu_resources + .window_swap_chains + .iter_mut() + // TODO: include non-primary swap chains + .filter(|(window_id, _swap_chain)| **window_id == primary_window_id.unwrap()) + .map(|(window_id, swap_chain)| { + let swap_chain_texture = swap_chain + .get_next_texture() + .expect("Timeout when acquiring next swap chain texture"); + (window_id.to_string(), swap_chain_texture) + }) + .collect::>(); + (primary_swap_chain, swap_chain_outputs) + } } impl Renderer for WgpuRenderer { @@ -444,18 +490,6 @@ impl Renderer for WgpuRenderer { let mut encoder = self.encoder.take().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 - .get_next_texture() - .expect("Timeout when acquiring next swap chain texture"); - - // setup, pipelines, bind groups, and resources let mut pipeline_storage = resources .get_mut::>() .unwrap(); @@ -485,7 +519,7 @@ impl Renderer for WgpuRenderer { &shader_storage, ); } - + // setup pipeline draw targets for draw_target_name in compiled_pipeline_descriptor.draw_targets.iter() { @@ -506,6 +540,8 @@ impl Renderer for WgpuRenderer { } } + let (primary_swap_chain, swap_chain_outputs) = self.get_swap_chain_outputs(resources); + // begin render passes for (pass_name, pass_descriptor) in render_graph.pass_descriptors.iter() { let mut render_pass = Self::create_render_pass( @@ -513,7 +549,8 @@ impl Renderer for WgpuRenderer { pass_descriptor, &global_render_resource_assignments, &mut encoder, - &frame, + &primary_swap_chain, + &swap_chain_outputs, ); if let Some(pass_pipelines) = render_graph.pass_pipelines.get(pass_name) { for pass_pipeline in pass_pipelines.iter() {