mirror of
https://github.com/bevyengine/bevy
synced 2025-02-16 22:18:33 +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 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())
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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 });
|
|
||||||
}
|
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>>()
|
||||||
|
|
|
@ -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>,
|
||||||
|
|
Loading…
Add table
Reference in a new issue