mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 04:33:37 +00:00
rework surface and swap chain creation to support arbitrary number of surfaces/windows
This commit is contained in:
parent
70b4100132
commit
17d4bec08c
13 changed files with 267 additions and 245 deletions
|
@ -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 bevy_transform::transform_system_bundle;
|
||||
|
||||
|
@ -20,7 +20,7 @@ impl AppPlugin for CorePlugin {
|
|||
app = app.add_system(transform_system);
|
||||
}
|
||||
|
||||
app = app.add_event::<WindowResize>()
|
||||
app = app.add_event::<WindowResized>()
|
||||
.add_event::<CreateWindow>()
|
||||
.add_event::<WindowCreated>()
|
||||
.add_resource(Windows::default())
|
||||
|
|
|
@ -70,7 +70,7 @@ where
|
|||
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 b_index = self.b_start_event_count - event_handle.last_event_count;
|
||||
event_handle.last_event_count = self.event_count;
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use super::{WindowDescriptor, WindowId};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct WindowResize {
|
||||
pub struct WindowResized {
|
||||
pub id: WindowId,
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
pub is_primary: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
|
@ -3,7 +3,7 @@ pub use winit_windows::*;
|
|||
|
||||
use crate::prelude::*;
|
||||
|
||||
use super::{CreateWindow, Window, WindowCreated, WindowResize, Windows};
|
||||
use super::{CreateWindow, Window, WindowCreated, WindowResized, Windows};
|
||||
use winit::{
|
||||
event,
|
||||
event::WindowEvent,
|
||||
|
@ -15,8 +15,7 @@ pub struct WinitPlugin;
|
|||
|
||||
impl AppPlugin for WinitPlugin {
|
||||
fn build(&self, app: AppBuilder) -> AppBuilder {
|
||||
app
|
||||
.add_resource(WinitWindows::default())
|
||||
app.add_resource(WinitWindows::default())
|
||||
.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 mut windows = app.resources.get_mut::<Windows>().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();
|
||||
window.width = size.width;
|
||||
window.height = size.height;
|
||||
|
||||
let mut resize_event = app.resources.get_mut::<Event<WindowResize>>().unwrap();
|
||||
resize_event.send(WindowResize {
|
||||
let mut resize_event = app.resources.get_mut::<Event<WindowResized>>().unwrap();
|
||||
resize_event.send(WindowResized {
|
||||
id: window_id,
|
||||
height: window.height,
|
||||
width: window.width,
|
||||
is_primary,
|
||||
});
|
||||
}
|
||||
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();
|
||||
for create_window_event in create_window_events.iter(create_window_event_handle) {
|
||||
let window = Window::new(&create_window_event.descriptor);
|
||||
create_window(
|
||||
&event_loop,
|
||||
&mut window_created_events,
|
||||
&mut winit_windows,
|
||||
&window,
|
||||
);
|
||||
winit_windows.create_window(event_loop, &window);
|
||||
window_created_events.send(WindowCreated { id: window.id });
|
||||
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 });
|
||||
}
|
||||
|
|
|
@ -14,14 +14,7 @@ use super::{
|
|||
AssetBatchers, EntityRenderResourceAssignments, RenderResourceAssignments,
|
||||
},
|
||||
};
|
||||
use crate::{
|
||||
app::{plugin::AppPlugin, AppBuilder},
|
||||
asset::AssetStorage,
|
||||
prelude::{
|
||||
LocalToWorld, Mesh, PipelineDescriptor, Shader, StandardMaterial, Texture,
|
||||
UniformResourceProvider,
|
||||
},
|
||||
};
|
||||
use crate::{core::WindowResized, prelude::*};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct RenderPlugin;
|
||||
|
@ -40,8 +33,12 @@ impl RenderPlugin {
|
|||
.add_draw_target(AssignedBatchesDrawTarget::default())
|
||||
.add_draw_target(AssignedMeshesDrawTarget::default())
|
||||
.add_draw_target(UiDrawTarget::default())
|
||||
.add_resource_provider(CameraResourceProvider::default())
|
||||
.add_resource_provider(Camera2dResourceProvider::default())
|
||||
.add_resource_provider(CameraResourceProvider::new(
|
||||
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(UiResourceProvider::new())
|
||||
.add_resource_provider(MeshResourceProvider::new())
|
||||
|
|
|
@ -18,13 +18,4 @@ pub trait ResourceProvider {
|
|||
_resources: &Resources,
|
||||
) {
|
||||
}
|
||||
fn resize(
|
||||
&mut self,
|
||||
_renderer: &mut dyn Renderer,
|
||||
_world: &mut World,
|
||||
_resources: &Resources,
|
||||
_width: u32,
|
||||
_height: u32,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,29 @@
|
|||
use crate::render::{
|
||||
use crate::{
|
||||
core::WindowResized,
|
||||
prelude::*,
|
||||
render::{
|
||||
render_resource::{
|
||||
resource_name, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments,
|
||||
ResourceProvider,
|
||||
BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments, ResourceProvider,
|
||||
},
|
||||
renderer::Renderer,
|
||||
ActiveCamera2d, Camera,
|
||||
},
|
||||
};
|
||||
use legion::prelude::*;
|
||||
use zerocopy::AsBytes;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Camera2dResourceProvider {
|
||||
pub camera_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 {
|
||||
|
@ -34,17 +45,22 @@ impl ResourceProvider for Camera2dResourceProvider {
|
|||
self.camera_buffer = Some(buffer);
|
||||
}
|
||||
|
||||
fn resize(
|
||||
&mut self,
|
||||
renderer: &mut dyn Renderer,
|
||||
world: &mut World,
|
||||
_resources: &Resources,
|
||||
width: u32,
|
||||
height: u32,
|
||||
) {
|
||||
fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, resources: &Resources) {
|
||||
let window_resized_events = resources.get::<Event<WindowResized>>().unwrap();
|
||||
let primary_window_resized_event = window_resized_events
|
||||
.iter(&mut self.window_resized_event_handle)
|
||||
.rev()
|
||||
.filter(|event| event.is_primary)
|
||||
.next();
|
||||
|
||||
if let Some(primary_window_resized_event) = 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) {
|
||||
camera.update(width, height);
|
||||
for (mut camera, _) in <(Write<Camera>, Read<ActiveCamera2d>)>::query().iter_mut(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 {
|
||||
|
@ -71,4 +87,5 @@ impl ResourceProvider for Camera2dResourceProvider {
|
|||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,31 @@
|
|||
use crate::render::{
|
||||
use crate::{
|
||||
core::WindowResized,
|
||||
prelude::*,
|
||||
render::{
|
||||
render_resource::{
|
||||
resource_name, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments,
|
||||
ResourceProvider,
|
||||
},
|
||||
renderer::Renderer,
|
||||
ActiveCamera, Camera,
|
||||
},
|
||||
};
|
||||
use bevy_transform::prelude::LocalToWorld;
|
||||
use legion::prelude::*;
|
||||
use zerocopy::AsBytes;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct CameraResourceProvider {
|
||||
pub camera_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 {
|
||||
|
@ -35,19 +47,22 @@ impl ResourceProvider for CameraResourceProvider {
|
|||
self.camera_buffer = Some(buffer);
|
||||
}
|
||||
|
||||
fn resize(
|
||||
&mut self,
|
||||
renderer: &mut dyn Renderer,
|
||||
world: &mut World,
|
||||
_resources: &Resources,
|
||||
width: u32,
|
||||
height: u32,
|
||||
) {
|
||||
fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, resources: &Resources) {
|
||||
let window_resized_events = resources.get::<Event<WindowResized>>().unwrap();
|
||||
let primary_window_resized_event = window_resized_events
|
||||
.iter(&mut self.window_resized_event_handle)
|
||||
.rev()
|
||||
.filter(|event| event.is_primary)
|
||||
.next();
|
||||
if let Some(primary_window_resized_event) = 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)
|
||||
{
|
||||
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 * local_to_world.0).to_cols_array_2d();
|
||||
|
||||
|
@ -75,4 +90,5 @@ impl ResourceProvider for CameraResourceProvider {
|
|||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@ use legion::prelude::Resources;
|
|||
pub struct FrameTextureResourceProvider {
|
||||
pub name: String,
|
||||
pub descriptor: TextureDescriptor,
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
}
|
||||
|
||||
impl FrameTextureResourceProvider {
|
||||
|
@ -19,12 +21,18 @@ impl FrameTextureResourceProvider {
|
|||
FrameTextureResourceProvider {
|
||||
name: name.to_string(),
|
||||
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 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.height = window.height;
|
||||
|
||||
|
@ -37,26 +45,11 @@ impl FrameTextureResourceProvider {
|
|||
let texture_resource = renderer.create_texture(&self.descriptor, None);
|
||||
render_resource_assignments.set(&self.name, texture_resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ResourceProvider for FrameTextureResourceProvider {
|
||||
fn initialize(
|
||||
&mut self,
|
||||
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);
|
||||
fn update(&mut self, renderer: &mut dyn Renderer, _world: &mut World, resources: &Resources) {
|
||||
self.update(renderer, resources)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ use crate::{
|
|||
use std::ops::Range;
|
||||
|
||||
pub trait Renderer {
|
||||
fn resize(&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_sampler(&mut self, sampler_descriptor: &SamplerDescriptor) -> RenderResource;
|
||||
|
|
|
@ -8,8 +8,8 @@ pub use wgpu_renderer::*;
|
|||
pub use wgpu_resources::*;
|
||||
|
||||
use crate::{
|
||||
app::{plugin::AppPlugin, AppBuilder, system_stage},
|
||||
core::{Event, WindowResize},
|
||||
app::{plugin::AppPlugin, system_stage, AppBuilder},
|
||||
core::{Event, WindowCreated, WindowResized},
|
||||
render::renderer::Renderer,
|
||||
};
|
||||
|
||||
|
@ -29,8 +29,12 @@ impl AppPlugin for WgpuRendererPlugin {
|
|||
}
|
||||
|
||||
pub fn wgpu_render_system(resources: &Resources) -> impl FnMut(&mut World, &mut Resources) {
|
||||
let window_resize_event = resources.get::<Event<WindowResize>>().unwrap();
|
||||
let mut wgpu_renderer = futures::executor::block_on(WgpuRenderer::new(window_resize_event.get_handle()));
|
||||
let window_resized_event = resources.get::<Event<WindowResized>>().unwrap();
|
||||
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| {
|
||||
wgpu_renderer.update(world, resources);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use super::{wgpu_type_converter::OwnedWgpuVertexBufferDescriptor, WgpuRenderPass, WgpuResources};
|
||||
use crate::{
|
||||
asset::{AssetStorage, Handle},
|
||||
core::{Event, EventHandle, WindowResize, winit::WinitWindows, Windows},
|
||||
core::{winit::WinitWindows, Event, EventHandle, WindowCreated, WindowResized, Windows, Window},
|
||||
legion::prelude::*,
|
||||
render::{
|
||||
pass::{
|
||||
|
@ -19,21 +19,29 @@ use crate::{
|
|||
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 device: Rc<RefCell<wgpu::Device>>,
|
||||
pub queue: wgpu::Queue,
|
||||
pub surface: Option<wgpu::Surface>,
|
||||
pub encoder: Option<wgpu::CommandEncoder>,
|
||||
pub render_pipelines: HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>,
|
||||
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,
|
||||
}
|
||||
|
||||
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(
|
||||
&wgpu::RequestAdapterOptions {
|
||||
power_preference: wgpu::PowerPreference::Default,
|
||||
|
@ -43,19 +51,21 @@ impl WgpuRenderer {
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
let (device, queue) = adapter.request_device(&wgpu::DeviceDescriptor {
|
||||
let (device, queue) = adapter
|
||||
.request_device(&wgpu::DeviceDescriptor {
|
||||
extensions: wgpu::Extensions {
|
||||
anisotropic_filtering: false,
|
||||
},
|
||||
limits: wgpu::Limits::default(),
|
||||
}).await;
|
||||
})
|
||||
.await;
|
||||
|
||||
WgpuRenderer {
|
||||
device: Rc::new(RefCell::new(device)),
|
||||
queue,
|
||||
surface: None,
|
||||
encoder: None,
|
||||
window_resize_handle: window_resize_event,
|
||||
window_resized_event_handle: window_resized_event_handle,
|
||||
window_created_event_handle,
|
||||
intialized: false,
|
||||
wgpu_resources: WgpuResources::default(),
|
||||
render_pipelines: HashMap::new(),
|
||||
|
@ -67,10 +77,7 @@ impl WgpuRenderer {
|
|||
return;
|
||||
}
|
||||
|
||||
self.create_surface(resources);
|
||||
self.initialize_resource_providers(world, resources);
|
||||
self.resize(world, resources);
|
||||
|
||||
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")]
|
||||
{
|
||||
let winit_windows = resources.get::<WinitWindows>().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 primary_winit_window = winit_windows.get_window(window.id).unwrap();
|
||||
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 resize(&mut self, world: &mut World, resources: &mut Resources) {
|
||||
if let Some(surface) = self.surface.as_ref() {
|
||||
self.encoder = Some(
|
||||
self.device
|
||||
.borrow()
|
||||
.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()
|
||||
};
|
||||
fn setup_swap_chain(&mut self, window: &Window) {
|
||||
let surface = self
|
||||
.wgpu_resources
|
||||
.window_surfaces
|
||||
.get(&window.id)
|
||||
.expect("Received window resized event for window without a wgpu surface");
|
||||
|
||||
let swap_chain_descriptor: wgpu::SwapChainDescriptor = window.into();
|
||||
let swap_chain = self
|
||||
.device
|
||||
.borrow()
|
||||
.create_swap_chain(surface, &swap_chain_descriptor);
|
||||
|
||||
// WgpuRenderer can't own swap_chain without creating lifetime ergonomics issues, so lets just store it in World.
|
||||
resources.insert(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");
|
||||
}
|
||||
self.wgpu_resources
|
||||
.window_swap_chains
|
||||
.insert(window.id, swap_chain);
|
||||
}
|
||||
}
|
||||
|
||||
impl Renderer for WgpuRenderer {
|
||||
fn update(&mut self, world: &mut World, resources: &mut 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
|
||||
// exposing the wgpu renderer internals to ResourceProvider traits. if this can be made cleaner that would be pretty cool.
|
||||
self.encoder = Some(
|
||||
|
@ -425,13 +433,17 @@ impl Renderer for WgpuRenderer {
|
|||
|
||||
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
|
||||
.get_next_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
|
||||
let mut pipeline_storage = resources
|
||||
.get_mut::<AssetStorage<PipelineDescriptor>>()
|
||||
|
|
|
@ -10,7 +10,7 @@ use crate::{
|
|||
},
|
||||
renderer::Renderer,
|
||||
texture::{SamplerDescriptor, TextureDescriptor},
|
||||
},
|
||||
}, core::WindowId,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
||||
|
@ -22,6 +22,8 @@ pub struct WgpuBindGroupInfo {
|
|||
#[derive(Default)]
|
||||
pub struct WgpuResources {
|
||||
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 textures: HashMap<RenderResource, wgpu::TextureView>,
|
||||
pub samplers: HashMap<RenderResource, wgpu::Sampler>,
|
||||
|
|
Loading…
Reference in a new issue