Added WgpuResizeReceiver to receive notifications on wgpu resizes.

This commit is contained in:
Filipe Rodrigues 2022-11-27 16:11:16 +00:00
parent 9b25ce1fef
commit 33ae975150
7 changed files with 75 additions and 15 deletions

1
Cargo.lock generated
View File

@ -3739,6 +3739,7 @@ dependencies = [
"futures",
"parking_lot",
"pollster",
"tokio",
"tracing",
"wgpu",
"winit",

View File

@ -18,7 +18,7 @@ pub use self::{
};
// Imports
use zsw_wgpu::{Wgpu, WgpuSurfaceResource};
use zsw_wgpu::{Wgpu, WgpuResizeReceiver, WgpuSurfaceResource};
/// Panels editor
@ -122,9 +122,10 @@ impl PanelsShader {
pub fn create(
wgpu: &Wgpu,
surface_resource: &mut WgpuSurfaceResource,
wgpu_resize_receiver: WgpuResizeReceiver,
) -> (PanelsRenderer, PanelsEditor, PanelsResource) {
(
PanelsRenderer::new(wgpu, surface_resource),
PanelsRenderer::new(wgpu, surface_resource, wgpu_resize_receiver),
PanelsEditor {},
PanelsResource {
panels: vec![],

View File

@ -14,7 +14,8 @@ use {
wgpu::util::DeviceExt,
winit::dpi::PhysicalSize,
zsw_img::{ImageReceiver, RawImageProvider},
zsw_wgpu::{Wgpu, WgpuSurfaceResource},
zsw_util::Services,
zsw_wgpu::{Wgpu, WgpuResizeReceiver, WgpuSurfaceResource},
};
/// Panels renderer
@ -48,12 +49,19 @@ pub struct PanelsRenderer {
/// Msaa frame-buffer
// TODO: Resize this on resize?
msaa_framebuffer: wgpu::TextureView,
/// Wgpu resizer
wgpu_resize_receiver: WgpuResizeReceiver,
}
impl PanelsRenderer {
/// Creates a new renderer for the panels
#[must_use]
pub fn new(wgpu: &Wgpu, surface_resource: &mut WgpuSurfaceResource) -> Self {
pub fn new(
wgpu: &Wgpu,
surface_resource: &mut WgpuSurfaceResource,
wgpu_resize_receiver: WgpuResizeReceiver,
) -> Self {
// Create the index buffer
let indices = self::create_indices(wgpu);
@ -79,7 +87,7 @@ impl PanelsRenderer {
);
// Create the framebuffer
let msaa_framebuffer = self::create_msaa_framebuffer(wgpu, surface_resource);
let msaa_framebuffer = self::create_msaa_framebuffer(wgpu, wgpu.surface_size(surface_resource));
Self {
pipelines: PanelsPipelines {
@ -91,6 +99,7 @@ impl PanelsRenderer {
uniforms_bind_group_layout,
image_bind_group_layout,
msaa_framebuffer,
wgpu_resize_receiver,
}
}
@ -120,15 +129,27 @@ impl PanelsRenderer {
}
/// Renders all panels
pub fn render(
&self,
#[allow(clippy::too_many_arguments)] // TODO: Refactor
pub fn render<S>(
&mut self,
services: &S,
resource: &PanelsResource,
cursor_pos: Point2<i32>,
queue: &wgpu::Queue,
encoder: &mut wgpu::CommandEncoder,
surface_view: &wgpu::TextureView,
surface_size: PhysicalSize<u32>,
) -> Result<(), anyhow::Error> {
) -> Result<(), anyhow::Error>
where
S: Services<Wgpu>,
{
// Resize out msaa framebuffer if needed
let last_resize = std::iter::from_fn(|| self.wgpu_resize_receiver.on_resize()).last();
if let Some(size) = last_resize {
tracing::debug!("Resizing msaa framebuffer to {}x{}", size.width, size.height);
self.msaa_framebuffer = self::create_msaa_framebuffer(services.service::<Wgpu>(), size);
}
// Create the render pass for all panels
let render_pass_color_attachment = match MSAA_SAMPLES {
1 => wgpu::RenderPassColorAttachment {
@ -344,8 +365,7 @@ fn create_render_pipeline(
}
/// Creates the msaa framebuffer
fn create_msaa_framebuffer(wgpu: &Wgpu, surface_resource: &mut WgpuSurfaceResource) -> wgpu::TextureView {
let size = wgpu.surface_size(surface_resource);
fn create_msaa_framebuffer(wgpu: &Wgpu, size: PhysicalSize<u32>) -> wgpu::TextureView {
let msaa_texture_extent = wgpu::Extent3d {
width: size.width,
height: size.height,

View File

@ -130,6 +130,7 @@ impl Renderer {
panels_renderer
.render(
services,
&panels_resource,
cursor_pos,
wgpu.queue(),

View File

@ -20,6 +20,7 @@ wgpu = { version = "0.14.0", features = ["serde", "replay"] }
# Async
futures = "0.3.25"
pollster = "0.2.5"
tokio = { version = "1.22.0", features = ["full", "tracing"] }
# Error handling
anyhow = "1.0.66"

View File

@ -13,6 +13,7 @@
use {
anyhow::Context,
std::sync::Arc,
tokio::sync::broadcast,
wgpu::TextureFormat,
winit::{dpi::PhysicalSize, window::Window},
zsw_input::InputReceiver,
@ -84,6 +85,9 @@ pub struct WgpuRenderer {
/// Surface texture format
surface_texture_format: Arc<TextureFormat>,
/// On resize sender
on_resize_tx: broadcast::Sender<PhysicalSize<u32>>,
}
impl WgpuRenderer {
@ -126,6 +130,9 @@ impl WgpuRenderer {
let config = self::window_surface_configuration(*self.surface_texture_format, size);
surface_resource.surface.configure(&self.device, &config);
surface_resource.size = size;
// Then send an event
let _ = self.on_resize_tx.send(size);
}
}
}
@ -146,6 +153,28 @@ impl WgpuRenderer {
}
}
/// Wgpu resize receiver
#[derive(Debug)]
pub struct WgpuResizeReceiver {
/// On resize receiver
on_resize_rx: broadcast::Receiver<PhysicalSize<u32>>,
}
impl Clone for WgpuResizeReceiver {
fn clone(&self) -> Self {
Self {
on_resize_rx: self.on_resize_rx.resubscribe(),
}
}
}
impl WgpuResizeReceiver {
/// Returns any last on-resize event, if any
pub fn on_resize(&mut self) -> Option<PhysicalSize<u32>> {
self.on_resize_rx.try_recv().ok()
}
}
/// A frame's rendering
#[derive(Debug)]
pub struct FrameRender {
@ -273,7 +302,9 @@ const fn window_surface_configuration(
/// Creates the `wgpu` services
pub async fn create(window: Arc<Window>) -> Result<(Wgpu, WgpuRenderer, WgpuSurfaceResource), anyhow::Error> {
pub async fn create(
window: Arc<Window>,
) -> Result<(Wgpu, WgpuRenderer, WgpuResizeReceiver, WgpuSurfaceResource), anyhow::Error> {
// Create the surface and adapter
// SAFETY: Due to the window being arced, and we storing it, we ensure the window outlives us and thus the surface
let (surface, adapter) = unsafe { self::create_surface_and_adapter(&window).await? };
@ -288,6 +319,7 @@ pub async fn create(window: Arc<Window>) -> Result<(Wgpu, WgpuRenderer, WgpuSurf
let surface_texture_format = Arc::new(surface_texture_format);
tracing::info!("Successfully initialized");
let (on_resize_tx, on_resize_rx) = broadcast::channel(16);
Ok((
Wgpu {
device: Arc::clone(&device),
@ -298,7 +330,9 @@ pub async fn create(window: Arc<Window>) -> Result<(Wgpu, WgpuRenderer, WgpuSurf
device,
queue,
surface_texture_format,
on_resize_tx,
},
WgpuResizeReceiver { on_resize_rx },
WgpuSurfaceResource {
surface,
size: surface_size,

View File

@ -50,12 +50,14 @@ pub async fn run(config: &Arc<Config>) -> Result<(), anyhow::Error> {
// Create all services and resources
// TODO: Execute futures in background and continue initializing
let (wgpu, mut wgpu_renderer, mut wgpu_surface_resource) = zsw_wgpu::create(Arc::clone(&window))
.await
.context("Unable to create renderer")?;
let (wgpu, mut wgpu_renderer, wgpu_resize_receiver, mut wgpu_surface_resource) =
zsw_wgpu::create(Arc::clone(&window))
.await
.context("Unable to create renderer")?;
let (playlist_runner, playlist_receiver, playlist_manager) = zsw_playlist::create();
let (image_loader, image_resizer, image_receiver) = zsw_img::loader::create();
let (mut panels_renderer, panels_editor, panels_resource) = zsw_panels::create(&wgpu, &mut wgpu_surface_resource);
let (mut panels_renderer, panels_editor, panels_resource) =
zsw_panels::create(&wgpu, &mut wgpu_surface_resource, wgpu_resize_receiver);
let (mut egui_renderer, mut egui_painter, mut egui_event_handler) = zsw_egui::create(&window, &wgpu);
let profiles_manager = zsw_profiles::create();
let (mut input_updater, mut input_receiver) = zsw_input::create();