use swap chain node

This commit is contained in:
Carter Anderson 2020-04-21 11:43:35 -07:00
parent 5fec31b63c
commit b6711d8eae
7 changed files with 97 additions and 105 deletions

View file

@ -40,21 +40,22 @@ use self::{
render_graph::RenderGraph, render_graph::RenderGraph,
render_resource::{ render_resource::{
entity_render_resource_assignments_system, entity_render_resource_assignments_system,
resource_providers::{ resource_providers::{LightResourceProvider, UniformResourceProvider},
LightResourceProvider,
UniformResourceProvider,
},
AssetBatchers, EntityRenderResourceAssignments, RenderResourceAssignments, AssetBatchers, EntityRenderResourceAssignments, RenderResourceAssignments,
}, },
shader::{uniforms::StandardMaterial, Shader}, shader::{uniforms::StandardMaterial, Shader},
texture::Texture, texture::Texture,
}; };
use bevy_app::{stage, AppBuilder, AppPlugin}; use bevy_app::{stage, AppBuilder, AppPlugin, GetEventReader};
use bevy_asset::AssetStorage; use bevy_asset::AssetStorage;
use bevy_transform::prelude::LocalToWorld; use bevy_transform::prelude::LocalToWorld;
use render_resource::resource_providers::{mesh_resource_provider_system}; use bevy_window::{WindowCreated, WindowResized};
use render_graph_2::{nodes::{Camera2dNode, CameraNode}, RenderGraph2}; use render_graph_2::{
nodes::{Camera2dNode, CameraNode, SwapChainWindowSource, WindowSwapChainNode},
RenderGraph2,
};
use render_resource::resource_providers::mesh_resource_provider_system;
pub static RENDER_RESOURCE_STAGE: &str = "render_resource"; pub static RENDER_RESOURCE_STAGE: &str = "render_resource";
pub static RENDER_STAGE: &str = "render"; pub static RENDER_STAGE: &str = "render";
@ -88,8 +89,14 @@ impl RenderPlugin {
impl AppPlugin for RenderPlugin { impl AppPlugin for RenderPlugin {
fn build(&self, app: &mut AppBuilder) { fn build(&self, app: &mut AppBuilder) {
let mut render_graph = RenderGraph2::default(); let mut render_graph = RenderGraph2::default();
render_graph.add_system_node(CameraNode::default(), app.resources_mut()); let resources = app.resources_mut();
render_graph.add_system_node(Camera2dNode::default(), app.resources_mut()); render_graph.add_system_node(CameraNode::default(), resources);
render_graph.add_system_node(Camera2dNode::default(), resources);
render_graph.add_node(WindowSwapChainNode::new(
SwapChainWindowSource::Primary,
resources.get_event_reader::<WindowCreated>(),
resources.get_event_reader::<WindowResized>(),
));
let mut asset_batchers = AssetBatchers::default(); let mut asset_batchers = AssetBatchers::default();
asset_batchers.batch_types2::<Mesh, StandardMaterial>(); asset_batchers.batch_types2::<Mesh, StandardMaterial>();
app.add_stage_after(stage::POST_UPDATE, RENDER_RESOURCE_STAGE) app.add_stage_after(stage::POST_UPDATE, RENDER_RESOURCE_STAGE)
@ -111,10 +118,7 @@ impl AppPlugin for RenderPlugin {
// core systems // core systems
.add_system(entity_render_resource_assignments_system()) .add_system(entity_render_resource_assignments_system())
.add_system_to_stage_init(stage::POST_UPDATE, camera::camera_update_system) .add_system_to_stage_init(stage::POST_UPDATE, camera::camera_update_system)
.add_system_to_stage( .add_system_to_stage(stage::POST_UPDATE, mesh::mesh_specializer_system())
stage::POST_UPDATE,
mesh::mesh_specializer_system(),
)
.add_system_to_stage(stage::POST_UPDATE, mesh::mesh_batcher_system()) .add_system_to_stage(stage::POST_UPDATE, mesh::mesh_batcher_system())
.add_system_to_stage( .add_system_to_stage(
stage::POST_UPDATE, stage::POST_UPDATE,

View file

@ -1,19 +1,41 @@
use crate::{ use crate::{
render_graph_2::{Node, ResourceBindings, ResourceSlot}, render_graph_2::{Node, ResourceBindings, ResourceSlot},
render_resource::{RenderResource, ResourceInfo}, render_resource::ResourceInfo,
renderer_2::RenderContext, renderer_2::RenderContext,
texture::TextureDescriptor,
}; };
use bevy_app::{EventReader, Events}; use bevy_app::{EventReader, Events};
use bevy_window::{WindowCreated, WindowId, WindowResized, Windows}; use bevy_window::{WindowCreated, WindowId, WindowResized, Windows};
use legion::prelude::*; use legion::prelude::*;
pub enum SwapChainWindowSource {
Primary,
Id(WindowId),
}
impl Default for SwapChainWindowSource {
fn default() -> Self {
SwapChainWindowSource::Primary
}
}
pub struct WindowSwapChainNode { pub struct WindowSwapChainNode {
window_id: WindowId, source_window: SwapChainWindowSource,
use_primary_window: bool,
window_resized_event_reader: EventReader<WindowResized>,
window_created_event_reader: EventReader<WindowCreated>, window_created_event_reader: EventReader<WindowCreated>,
swap_chain_resource: Option<RenderResource>, window_resized_event_reader: EventReader<WindowResized>,
}
impl WindowSwapChainNode {
pub fn new(
source_window: SwapChainWindowSource,
window_created_event_reader: EventReader<WindowCreated>,
window_resized_event_reader: EventReader<WindowResized>,
) -> Self {
WindowSwapChainNode {
source_window,
window_created_event_reader,
window_resized_event_reader,
}
}
} }
impl Node for WindowSwapChainNode { impl Node for WindowSwapChainNode {
@ -39,32 +61,30 @@ impl Node for WindowSwapChainNode {
let windows = resources.get::<Windows>().unwrap(); let windows = resources.get::<Windows>().unwrap();
let render_resources = render_context.resources_mut(); let render_resources = render_context.resources_mut();
let window = if self.use_primary_window { let window = match self.source_window {
windows.get_primary().expect("No primary window exists") SwapChainWindowSource::Primary => {
} else { windows.get_primary().expect("No primary window exists")
windows }
.get(self.window_id) SwapChainWindowSource::Id(id) => windows
.expect("Received window resized event for non-existent window") .get(id)
.expect("Received window resized event for non-existent window"),
}; };
// create window swapchain // create window swapchain
if let Some(_) = window_created_events if let Some(_) = window_created_events
.find_latest(&mut self.window_created_event_reader, |e| { .find_latest(&mut self.window_created_event_reader, |e| e.id == window.id)
e.id == window.id
})
{ {
render_resources.create_swap_chain(window); render_resources.create_swap_chain(window);
} }
// resize window swapchain // resize window swapchain
if let Some(_) = window_resized_events if let Some(_) = window_resized_events
.find_latest(&mut self.window_resized_event_reader, |e| { .find_latest(&mut self.window_resized_event_reader, |e| e.id == window.id)
e.id == window.id
})
{ {
render_resources.create_swap_chain(window); render_resources.create_swap_chain(window);
} }
output.set(WINDOW_TEXTURE, self.swap_chain_resource.unwrap()); let swap_chain_texture = render_resources.next_swap_chain_texture(window.id);
output.set(WINDOW_TEXTURE, swap_chain_texture);
} }
} }

View file

@ -24,8 +24,9 @@ impl GlobalRenderResourceContext {
pub trait RenderResourceContext: Downcast + Send + Sync + 'static { pub trait RenderResourceContext: Downcast + Send + Sync + 'static {
fn create_swap_chain(&self, window: &Window); fn create_swap_chain(&self, window: &Window);
fn next_swap_chain_texture(&self, window_id: WindowId); fn next_swap_chain_texture(&self, window_id: WindowId) -> RenderResource;
fn drop_swap_chain_texture(&self, window_id: WindowId); fn drop_swap_chain_texture(&self, render_resource: RenderResource);
fn drop_all_swap_chain_textures(&self);
fn create_sampler(&self, sampler_descriptor: &SamplerDescriptor) -> RenderResource; fn create_sampler(&self, sampler_descriptor: &SamplerDescriptor) -> RenderResource;
fn create_texture(&self, texture_descriptor: &TextureDescriptor) -> RenderResource; fn create_texture(&self, texture_descriptor: &TextureDescriptor) -> RenderResource;
fn create_buffer(&self, buffer_info: BufferInfo) -> RenderResource; fn create_buffer(&self, buffer_info: BufferInfo) -> RenderResource;

View file

@ -426,7 +426,6 @@ impl RenderContext for WgpuRenderContext {
let mut encoder = self.command_encoder.take().unwrap(); let mut encoder = self.command_encoder.take().unwrap();
{ {
let render_pass = create_render_pass( let render_pass = create_render_pass(
self,
pass_descriptor, pass_descriptor,
render_resource_assignments, render_resource_assignments,
&refs, &refs,
@ -447,7 +446,6 @@ impl RenderContext for WgpuRenderContext {
} }
pub fn create_render_pass<'a, 'b>( pub fn create_render_pass<'a, 'b>(
render_context: &'a WgpuRenderContext,
pass_descriptor: &PassDescriptor, pass_descriptor: &PassDescriptor,
global_render_resource_assignments: &'b RenderResourceAssignments, global_render_resource_assignments: &'b RenderResourceAssignments,
refs: &WgpuResourceRefs<'a>, refs: &WgpuResourceRefs<'a>,
@ -459,7 +457,6 @@ pub fn create_render_pass<'a, 'b>(
.iter() .iter()
.map(|c| { .map(|c| {
create_wgpu_color_attachment_descriptor( create_wgpu_color_attachment_descriptor(
render_context,
global_render_resource_assignments, global_render_resource_assignments,
refs, refs,
c, c,
@ -468,7 +465,6 @@ pub fn create_render_pass<'a, 'b>(
.collect::<Vec<wgpu::RenderPassColorAttachmentDescriptor>>(), .collect::<Vec<wgpu::RenderPassColorAttachmentDescriptor>>(),
depth_stencil_attachment: pass_descriptor.depth_stencil_attachment.as_ref().map(|d| { depth_stencil_attachment: pass_descriptor.depth_stencil_attachment.as_ref().map(|d| {
create_wgpu_depth_stencil_attachment_descriptor( create_wgpu_depth_stencil_attachment_descriptor(
render_context,
global_render_resource_assignments, global_render_resource_assignments,
refs, refs,
d, d,
@ -478,7 +474,6 @@ pub fn create_render_pass<'a, 'b>(
} }
fn get_texture_view<'a>( fn get_texture_view<'a>(
render_context: &'a WgpuRenderContext,
global_render_resource_assignments: &RenderResourceAssignments, global_render_resource_assignments: &RenderResourceAssignments,
refs: &WgpuResourceRefs<'a>, refs: &WgpuResourceRefs<'a>,
name: &str, name: &str,
@ -487,10 +482,10 @@ fn get_texture_view<'a>(
resource_name::texture::SWAP_CHAIN => { resource_name::texture::SWAP_CHAIN => {
if let Some(primary_swap_chain) = refs if let Some(primary_swap_chain) = refs
.swap_chain_outputs .swap_chain_outputs
.get(render_context.primary_window.as_ref().unwrap()) .values()
.map(|output| &output.view) .next()
{ {
primary_swap_chain &primary_swap_chain.view
} else { } else {
panic!("No primary swap chain found for color attachment"); panic!("No primary swap chain found for color attachment");
} }
@ -509,13 +504,11 @@ fn get_texture_view<'a>(
} }
fn create_wgpu_color_attachment_descriptor<'a>( fn create_wgpu_color_attachment_descriptor<'a>(
render_context: &'a WgpuRenderContext,
global_render_resource_assignments: &RenderResourceAssignments, global_render_resource_assignments: &RenderResourceAssignments,
refs: &WgpuResourceRefs<'a>, refs: &WgpuResourceRefs<'a>,
color_attachment_descriptor: &RenderPassColorAttachmentDescriptor, color_attachment_descriptor: &RenderPassColorAttachmentDescriptor,
) -> wgpu::RenderPassColorAttachmentDescriptor<'a> { ) -> wgpu::RenderPassColorAttachmentDescriptor<'a> {
let attachment = get_texture_view( let attachment = get_texture_view(
render_context,
global_render_resource_assignments, global_render_resource_assignments,
refs, refs,
color_attachment_descriptor.attachment.as_str(), color_attachment_descriptor.attachment.as_str(),
@ -526,7 +519,6 @@ fn create_wgpu_color_attachment_descriptor<'a>(
.as_ref() .as_ref()
.map(|target| { .map(|target| {
get_texture_view( get_texture_view(
render_context,
global_render_resource_assignments, global_render_resource_assignments,
refs, refs,
target.as_str(), target.as_str(),
@ -543,13 +535,11 @@ fn create_wgpu_color_attachment_descriptor<'a>(
} }
fn create_wgpu_depth_stencil_attachment_descriptor<'a>( fn create_wgpu_depth_stencil_attachment_descriptor<'a>(
render_context: &'a WgpuRenderContext,
global_render_resource_assignments: &RenderResourceAssignments, global_render_resource_assignments: &RenderResourceAssignments,
refs: &WgpuResourceRefs<'a>, refs: &WgpuResourceRefs<'a>,
depth_stencil_attachment_descriptor: &RenderPassDepthStencilAttachmentDescriptor, depth_stencil_attachment_descriptor: &RenderPassDepthStencilAttachmentDescriptor,
) -> wgpu::RenderPassDepthStencilAttachmentDescriptor<'a> { ) -> wgpu::RenderPassDepthStencilAttachmentDescriptor<'a> {
let attachment = get_texture_view( let attachment = get_texture_view(
render_context,
global_render_resource_assignments, global_render_resource_assignments,
refs, refs,
depth_stencil_attachment_descriptor.attachment.as_str(), depth_stencil_attachment_descriptor.attachment.as_str(),

View file

@ -7,7 +7,7 @@ use bevy_render::{
shader::Shader, shader::Shader,
texture::{SamplerDescriptor, TextureDescriptor}, texture::{SamplerDescriptor, TextureDescriptor},
}; };
use bevy_window::{Window, WindowId}; use bevy_window::Window;
use std::sync::Arc; use std::sync::Arc;
#[derive(Clone)] #[derive(Clone)]
@ -99,11 +99,15 @@ impl RenderResourceContext for WgpuRenderResourceContext {
self.wgpu_resources self.wgpu_resources
.create_window_swap_chain(&self.device, window) .create_window_swap_chain(&self.device, window)
} }
fn next_swap_chain_texture(&self, window_id: bevy_window::WindowId) { fn next_swap_chain_texture(&self, window_id: bevy_window::WindowId) -> RenderResource {
self.wgpu_resources.next_swap_chain_texture(window_id); self.wgpu_resources.next_swap_chain_texture(window_id)
} }
fn drop_swap_chain_texture(&self, window_id: WindowId) { fn drop_swap_chain_texture(&self, render_resource: RenderResource) {
self.wgpu_resources.remove_swap_chain_texture(window_id); self.wgpu_resources
.remove_swap_chain_texture(render_resource);
}
fn drop_all_swap_chain_textures(&self) {
self.wgpu_resources.remove_all_swap_chain_textures();
} }
fn set_asset_resource_untyped( fn set_asset_resource_untyped(
&self, &self,

View file

@ -12,7 +12,7 @@ use bevy_render::{
}; };
use bevy_window::{WindowCreated, WindowResized, Windows}; use bevy_window::{WindowCreated, WindowResized, Windows};
use legion::prelude::*; use legion::prelude::*;
use std::{collections::HashSet, ops::Deref, sync::Arc}; use std::{ops::Deref, sync::Arc};
pub struct WgpuRenderer { pub struct WgpuRenderer {
pub device: Arc<wgpu::Device>, pub device: Arc<wgpu::Device>,
pub queue: wgpu::Queue, pub queue: wgpu::Queue,
@ -171,35 +171,6 @@ impl WgpuRenderer {
} }
} }
pub fn handle_window_resized_events(
&mut self,
resources: &Resources,
global_render_resources: &dyn RenderResourceContext,
) {
let windows = resources.get::<Windows>().unwrap();
let window_resized_events = resources.get::<Events<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_reader)
.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");
// TODO: consider making this a WgpuRenderContext method
global_render_resources.create_swap_chain(window);
handled_windows.insert(window_resized_event.id);
}
}
pub fn handle_window_created_events( pub fn handle_window_created_events(
&mut self, &mut self,
resources: &Resources, resources: &Resources,
@ -216,12 +187,11 @@ impl WgpuRenderer {
#[cfg(feature = "bevy_winit")] #[cfg(feature = "bevy_winit")]
{ {
let winit_windows = resources.get::<bevy_winit::WinitWindows>().unwrap(); let winit_windows = resources.get::<bevy_winit::WinitWindows>().unwrap();
let primary_winit_window = winit_windows.get_window(window.id).unwrap(); let winit_window = winit_windows.get_window(window.id).unwrap();
let surface = wgpu::Surface::create(primary_winit_window.deref()); let surface = wgpu::Surface::create(winit_window.deref());
global_render_resource_context global_render_resource_context
.wgpu_resources .wgpu_resources
.set_window_surface(window.id, surface); .set_window_surface(window.id, surface);
global_render_resource_context.create_swap_chain(window);
} }
} }
} }
@ -251,7 +221,13 @@ impl WgpuRenderer {
for mut stage in linear_scheduler.get_stages(&mut render_graph) { for mut stage in linear_scheduler.get_stages(&mut render_graph) {
for job in stage.iter_mut() { for job in stage.iter_mut() {
for node_state in job.iter_mut() { for node_state in job.iter_mut() {
node_state.node.update(world, resources, &mut render_context, &node_state.input, &mut node_state.output); node_state.node.update(
world,
resources,
&mut render_context,
&node_state.input,
&mut node_state.output,
);
} }
} }
} }
@ -263,7 +239,6 @@ impl WgpuRenderer {
} }
pub fn update(&mut self, world: &mut World, resources: &mut Resources) { pub fn update(&mut self, world: &mut World, resources: &mut Resources) {
self.run_graph(world, resources);
let mut encoder = { let mut encoder = {
let mut global_context = resources.get_mut::<GlobalRenderResourceContext>().unwrap(); let mut global_context = resources.get_mut::<GlobalRenderResourceContext>().unwrap();
let render_resource_context = global_context let render_resource_context = global_context
@ -273,7 +248,6 @@ impl WgpuRenderer {
self.handle_window_created_events(resources, render_resource_context); self.handle_window_created_events(resources, render_resource_context);
self.handle_window_resized_events(resources, render_resource_context);
let mut render_context = let mut render_context =
WgpuRenderContext::new(self.device.clone(), render_resource_context.clone()); WgpuRenderContext::new(self.device.clone(), render_resource_context.clone());
if !self.intialized { if !self.intialized {
@ -292,6 +266,7 @@ impl WgpuRenderer {
render_context.command_encoder.take() render_context.command_encoder.take()
}; };
self.run_graph(world, resources);
// TODO: add to POST_UPDATE and remove redundant global_context // TODO: add to POST_UPDATE and remove redundant global_context
render_resource_sets_system().run(world, resources); render_resource_sets_system().run(world, resources);
let mut global_context = resources.get_mut::<GlobalRenderResourceContext>().unwrap(); let mut global_context = resources.get_mut::<GlobalRenderResourceContext>().unwrap();
@ -317,9 +292,6 @@ impl WgpuRenderer {
.get_primary() .get_primary()
.map(|window| window.id); .map(|window| window.id);
if let Some(primary_window_id) = primary_window_id { if let Some(primary_window_id) = primary_window_id {
render_context
.render_resources
.next_swap_chain_texture(primary_window_id);
render_context.primary_window = Some(primary_window_id); render_context.primary_window = Some(primary_window_id);
} }
@ -371,11 +343,9 @@ impl WgpuRenderer {
self.queue.submit(&[command_buffer]); self.queue.submit(&[command_buffer]);
} }
// clear primary swap chain texture // clear swap chain textures
if let Some(primary_window_id) = primary_window_id { render_context
render_context .render_resources
.render_resources .drop_all_swap_chain_textures();
.drop_swap_chain_texture(primary_window_id);
}
} }
} }

View file

@ -43,7 +43,7 @@ pub struct WgpuBindGroupInfo {
pub struct WgpuResourcesReadLock<'a> { pub struct WgpuResourcesReadLock<'a> {
pub buffers: RwLockReadGuard<'a, HashMap<RenderResource, wgpu::Buffer>>, pub buffers: RwLockReadGuard<'a, HashMap<RenderResource, wgpu::Buffer>>,
pub textures: RwLockReadGuard<'a, HashMap<RenderResource, wgpu::TextureView>>, pub textures: RwLockReadGuard<'a, HashMap<RenderResource, wgpu::TextureView>>,
pub swap_chain_outputs: RwLockReadGuard<'a, HashMap<WindowId, wgpu::SwapChainOutput>>, pub swap_chain_outputs: RwLockReadGuard<'a, HashMap<RenderResource, wgpu::SwapChainOutput>>,
pub render_pipelines: pub render_pipelines:
RwLockReadGuard<'a, HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>>, RwLockReadGuard<'a, HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>>,
pub bind_groups: RwLockReadGuard<'a, HashMap<BindGroupDescriptorId, WgpuBindGroupInfo>>, pub bind_groups: RwLockReadGuard<'a, HashMap<BindGroupDescriptorId, WgpuBindGroupInfo>>,
@ -65,7 +65,7 @@ impl<'a> WgpuResourcesReadLock<'a> {
pub struct WgpuResourceRefs<'a> { pub struct WgpuResourceRefs<'a> {
pub buffers: &'a HashMap<RenderResource, wgpu::Buffer>, pub buffers: &'a HashMap<RenderResource, wgpu::Buffer>,
pub textures: &'a HashMap<RenderResource, wgpu::TextureView>, pub textures: &'a HashMap<RenderResource, wgpu::TextureView>,
pub swap_chain_outputs: &'a HashMap<WindowId, wgpu::SwapChainOutput>, pub swap_chain_outputs: &'a HashMap<RenderResource, wgpu::SwapChainOutput>,
pub render_pipelines: &'a HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>, pub render_pipelines: &'a HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>,
pub bind_groups: &'a HashMap<BindGroupDescriptorId, WgpuBindGroupInfo>, pub bind_groups: &'a HashMap<BindGroupDescriptorId, WgpuBindGroupInfo>,
} }
@ -75,7 +75,7 @@ pub struct WgpuResources {
// TODO: remove this from WgpuResources. it doesn't need to be here // TODO: remove this from WgpuResources. it doesn't need to be here
pub window_surfaces: Arc<RwLock<HashMap<WindowId, wgpu::Surface>>>, pub window_surfaces: Arc<RwLock<HashMap<WindowId, wgpu::Surface>>>,
pub window_swap_chains: Arc<RwLock<HashMap<WindowId, wgpu::SwapChain>>>, pub window_swap_chains: Arc<RwLock<HashMap<WindowId, wgpu::SwapChain>>>,
pub swap_chain_outputs: Arc<RwLock<HashMap<WindowId, wgpu::SwapChainOutput>>>, pub swap_chain_outputs: Arc<RwLock<HashMap<RenderResource, wgpu::SwapChainOutput>>>,
pub buffers: Arc<RwLock<HashMap<RenderResource, wgpu::Buffer>>>, pub buffers: Arc<RwLock<HashMap<RenderResource, wgpu::Buffer>>>,
pub textures: Arc<RwLock<HashMap<RenderResource, wgpu::TextureView>>>, pub textures: Arc<RwLock<HashMap<RenderResource, wgpu::TextureView>>>,
pub samplers: Arc<RwLock<HashMap<RenderResource, wgpu::Sampler>>>, pub samplers: Arc<RwLock<HashMap<RenderResource, wgpu::Sampler>>>,
@ -105,18 +105,21 @@ impl WgpuResources {
.insert(window_id, surface); .insert(window_id, surface);
} }
pub fn next_swap_chain_texture(&self, window_id: WindowId) { pub fn next_swap_chain_texture(&self, window_id: WindowId) -> RenderResource {
let mut swap_chain_outputs = self.window_swap_chains.write().unwrap(); let mut swap_chain_outputs = self.window_swap_chains.write().unwrap();
let swap_chain_output = swap_chain_outputs.get_mut(&window_id).unwrap(); let swap_chain_output = swap_chain_outputs.get_mut(&window_id).unwrap();
let next_texture = swap_chain_output.get_next_texture().unwrap(); let next_texture = swap_chain_output.get_next_texture().unwrap();
let render_resource = RenderResource::new();
// TODO: Add ResourceInfo
self.swap_chain_outputs self.swap_chain_outputs
.write() .write()
.unwrap() .unwrap()
.insert(window_id, next_texture); .insert(render_resource, next_texture);
render_resource
} }
pub fn remove_swap_chain_texture(&self, window_id: WindowId) { pub fn remove_swap_chain_texture(&self, render_resource: RenderResource) {
self.swap_chain_outputs.write().unwrap().remove(&window_id); self.swap_chain_outputs.write().unwrap().remove(&render_resource);
} }
pub fn remove_all_swap_chain_textures(&self) { pub fn remove_all_swap_chain_textures(&self) {