From 158562031fae9f86f4eb80d4f2a88eac1d632fef Mon Sep 17 00:00:00 2001 From: galister <22305755+galister@users.noreply.github.com> Date: Wed, 25 Jun 2025 21:06:05 +0900 Subject: [PATCH] wgui: introduce SharedContext to share between Contexts --- uidev/src/main.rs | 541 +++++++++--------- wgui/src/renderer_vk/context.rs | 121 ++-- wlx-overlay-s/src/gui/panel.rs | 14 +- .../src/overlays/keyboard/builder.rs | 2 +- wlx-overlay-s/src/state.rs | 7 +- 5 files changed, 363 insertions(+), 322 deletions(-) diff --git a/uidev/src/main.rs b/uidev/src/main.rs index 12bd21f..eb29a3a 100644 --- a/uidev/src/main.rs +++ b/uidev/src/main.rs @@ -8,24 +8,25 @@ use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::util::SubscriberInitExt; use vulkan::init_window; use vulkano::{ - Validated, VulkanError, - command_buffer::CommandBufferUsage, - format::Format, - image::{ImageUsage, view::ImageView}, - swapchain::{ - Surface, SurfaceInfo, Swapchain, SwapchainCreateInfo, SwapchainPresentInfo, acquire_next_image, - }, - sync::GpuFuture, + Validated, VulkanError, + command_buffer::CommandBufferUsage, + format::Format, + image::{ImageUsage, view::ImageView}, + swapchain::{ + Surface, SurfaceInfo, Swapchain, SwapchainCreateInfo, SwapchainPresentInfo, + acquire_next_image, + }, + sync::GpuFuture, }; use wgui::{ - event::{MouseButton, MouseDownEvent, MouseMotionEvent, MouseUpEvent, MouseWheelEvent}, - gfx::WGfx, - renderer_vk::{self}, + event::{MouseButton, MouseDownEvent, MouseMotionEvent, MouseUpEvent, MouseWheelEvent}, + gfx::WGfx, + renderer_vk::{self}, }; use winit::{ - event::{ElementState, Event, MouseScrollDelta, WindowEvent}, - event_loop::ControlFlow, - keyboard::{KeyCode, PhysicalKey}, + event::{ElementState, Event, MouseScrollDelta, WindowEvent}, + event_loop::ControlFlow, + keyboard::{KeyCode, PhysicalKey}, }; use crate::testbed::{testbed_dashboard::TestbedDashboard, testbed_generic::TestbedGeneric}; @@ -37,304 +38,312 @@ mod timestep; mod vulkan; fn init_logging() { - tracing_subscriber::registry() - .with( - tracing_subscriber::fmt::layer() - .pretty() - .with_writer(std::io::stderr), - ) - .with( - /* read RUST_LOG env var */ - EnvFilter::builder() - .with_default_directive(LevelFilter::DEBUG.into()) - .from_env_lossy(), - ) - .init(); + tracing_subscriber::registry() + .with( + tracing_subscriber::fmt::layer() + .pretty() + .with_writer(std::io::stderr), + ) + .with( + /* read RUST_LOG env var */ + EnvFilter::builder() + .with_default_directive(LevelFilter::DEBUG.into()) + .from_env_lossy(), + ) + .init(); } fn load_testbed() -> anyhow::Result> { - let name = std::env::var("TESTBED").unwrap_or_default(); - Ok(match name.as_str() { - "dashboard" => Box::new(TestbedDashboard::new()?), - "" => Box::new(TestbedGeneric::new()?), - _ => Box::new(TestbedAny::new(&name)?), - }) + let name = std::env::var("TESTBED").unwrap_or_default(); + Ok(match name.as_str() { + "dashboard" => Box::new(TestbedDashboard::new()?), + "" => Box::new(TestbedGeneric::new()?), + _ => Box::new(TestbedAny::new(&name)?), + }) } fn main() -> Result<(), Box> { - init_logging(); + init_logging(); - let (gfx, event_loop, window, surface) = init_window()?; - let inner_size = window.inner_size(); - let mut swapchain_size = [inner_size.width, inner_size.height]; + let (gfx, event_loop, window, surface) = init_window()?; + let inner_size = window.inner_size(); + let mut swapchain_size = [inner_size.width, inner_size.height]; - let mut swapchain_create_info = - swapchain_create_info(&gfx, gfx.surface_format, surface.clone(), swapchain_size); + let mut swapchain_create_info = + swapchain_create_info(&gfx, gfx.surface_format, surface.clone(), swapchain_size); - let (mut swapchain, mut images) = { - let (swapchain, images) = Swapchain::new( - gfx.device.clone(), - surface.clone(), - swapchain_create_info.clone(), - )?; + let (mut swapchain, mut images) = { + let (swapchain, images) = Swapchain::new( + gfx.device.clone(), + surface.clone(), + swapchain_create_info.clone(), + )?; - let image_views = images - .into_iter() - .map(|image| ImageView::new_default(image).unwrap()) - .collect::>(); + let image_views = images + .into_iter() + .map(|image| ImageView::new_default(image).unwrap()) + .collect::>(); - (swapchain, image_views) - }; + (swapchain, image_views) + }; - let mut recreate = false; - let mut last_draw = std::time::Instant::now(); + let mut recreate = false; + let mut last_draw = std::time::Instant::now(); - let mut scale = window.scale_factor() as f32; + let mut scale = window.scale_factor() as f32; - let mut testbed = load_testbed()?; + let mut testbed = load_testbed()?; - let mut mouse = Vec2::ZERO; + let mut mouse = Vec2::ZERO; - let mut render_context = - renderer_vk::context::Context::new(gfx.clone(), gfx.surface_format, scale)?; + let mut shared_context = renderer_vk::context::SharedContext::new(gfx.clone())?; + let mut render_context = renderer_vk::context::Context::new(&mut shared_context, scale)?; - render_context.update_viewport(swapchain_size, scale)?; - println!("new swapchain_size: {swapchain_size:?}"); + render_context.update_viewport(&mut shared_context, swapchain_size, scale)?; + println!("new swapchain_size: {swapchain_size:?}"); - let mut profiler = profiler::Profiler::new(100); - let mut frame_index: u64 = 0; + let mut profiler = profiler::Profiler::new(100); + let mut frame_index: u64 = 0; - let mut timestep = Timestep::new(); - timestep.set_tps(60.0); + let mut timestep = Timestep::new(); + timestep.set_tps(60.0); - #[allow(deprecated)] - event_loop.run(move |event, elwt| { - elwt.set_control_flow(ControlFlow::Poll); + #[allow(deprecated)] + event_loop.run(move |event, elwt| { + elwt.set_control_flow(ControlFlow::Poll); - match event { - Event::WindowEvent { - event: WindowEvent::MouseWheel { delta, .. }, - .. - } => match delta { - MouseScrollDelta::LineDelta(x, y) => testbed - .layout() - .push_event(&wgui::event::Event::MouseWheel(MouseWheelEvent { - shift: Vec2::new(x, y), - pos: mouse / scale, - device: 0, - })) - .unwrap(), - MouseScrollDelta::PixelDelta(pos) => testbed - .layout() - .push_event(&wgui::event::Event::MouseWheel(MouseWheelEvent { - shift: Vec2::new(pos.x as f32 / 5.0, pos.y as f32 / 5.0), - pos: mouse / scale, - device: 0, - })) - .unwrap(), - }, - Event::WindowEvent { - event: WindowEvent::MouseInput { state, button, .. }, - .. - } => { - if matches!(button, winit::event::MouseButton::Left) { - if matches!(state, winit::event::ElementState::Pressed) { - testbed - .layout() - .push_event(&wgui::event::Event::MouseDown(MouseDownEvent { - pos: mouse / scale, - button: MouseButton::Left, - device: 0, - })) - .unwrap(); - } else { - testbed - .layout() - .push_event(&wgui::event::Event::MouseUp(MouseUpEvent { - pos: mouse / scale, - button: MouseButton::Left, - device: 0, - })) - .unwrap(); - } - } - } - Event::WindowEvent { - event: WindowEvent::CursorMoved { position, .. }, - .. - } => { - mouse = vec2(position.x as _, position.y as _); - testbed - .layout() - .push_event(&wgui::event::Event::MouseMotion(MouseMotionEvent { - pos: mouse / scale, - device: 0, - })) - .unwrap(); - } - Event::WindowEvent { - event: WindowEvent::KeyboardInput { event, .. }, - .. - } => { - if event.state == ElementState::Pressed { - if event.physical_key == PhysicalKey::Code(KeyCode::Equal) { - scale *= 1.25; - render_context - .update_viewport(swapchain_size, scale) - .unwrap(); - } + match event { + Event::WindowEvent { + event: WindowEvent::MouseWheel { delta, .. }, + .. + } => match delta { + MouseScrollDelta::LineDelta(x, y) => testbed + .layout() + .push_event(&wgui::event::Event::MouseWheel(MouseWheelEvent { + shift: Vec2::new(x, y), + pos: mouse / scale, + device: 0, + })) + .unwrap(), + MouseScrollDelta::PixelDelta(pos) => testbed + .layout() + .push_event(&wgui::event::Event::MouseWheel(MouseWheelEvent { + shift: Vec2::new(pos.x as f32 / 5.0, pos.y as f32 / 5.0), + pos: mouse / scale, + device: 0, + })) + .unwrap(), + }, + Event::WindowEvent { + event: WindowEvent::MouseInput { state, button, .. }, + .. + } => { + if matches!(button, winit::event::MouseButton::Left) { + if matches!(state, winit::event::ElementState::Pressed) { + testbed + .layout() + .push_event(&wgui::event::Event::MouseDown(MouseDownEvent { + pos: mouse / scale, + button: MouseButton::Left, + device: 0, + })) + .unwrap(); + } else { + testbed + .layout() + .push_event(&wgui::event::Event::MouseUp(MouseUpEvent { + pos: mouse / scale, + button: MouseButton::Left, + device: 0, + })) + .unwrap(); + } + } + } + Event::WindowEvent { + event: WindowEvent::CursorMoved { position, .. }, + .. + } => { + mouse = vec2(position.x as _, position.y as _); + testbed + .layout() + .push_event(&wgui::event::Event::MouseMotion(MouseMotionEvent { + pos: mouse / scale, + device: 0, + })) + .unwrap(); + } + Event::WindowEvent { + event: WindowEvent::KeyboardInput { event, .. }, + .. + } => { + if event.state == ElementState::Pressed { + if event.physical_key == PhysicalKey::Code(KeyCode::Equal) { + scale *= 1.25; + render_context + .update_viewport(&mut shared_context, swapchain_size, scale) + .unwrap(); + } - if event.physical_key == PhysicalKey::Code(KeyCode::Minus) { - scale *= 0.75; - render_context - .update_viewport(swapchain_size, scale) - .unwrap(); - } - } - } - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => { - elwt.exit(); - } - Event::WindowEvent { - event: WindowEvent::Resized(_), - .. - } => { - recreate = true; - } - Event::WindowEvent { - event: WindowEvent::RedrawRequested, - .. - } => { - if recreate { - let inner_size = window.inner_size(); - swapchain_size = [inner_size.width, inner_size.height]; + if event.physical_key == PhysicalKey::Code(KeyCode::Minus) { + scale *= 0.75; + render_context + .update_viewport(&mut shared_context, swapchain_size, scale) + .unwrap(); + } + } + } + Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } => { + elwt.exit(); + } + Event::WindowEvent { + event: WindowEvent::Resized(_), + .. + } => { + recreate = true; + } + Event::WindowEvent { + event: WindowEvent::RedrawRequested, + .. + } => { + if recreate { + let inner_size = window.inner_size(); + swapchain_size = [inner_size.width, inner_size.height]; - swapchain_create_info.image_extent = swapchain_size; + swapchain_create_info.image_extent = swapchain_size; - (swapchain, images) = { - let (swapchain, images) = swapchain.recreate(swapchain_create_info.clone()).unwrap(); + (swapchain, images) = { + let (swapchain, images) = + swapchain.recreate(swapchain_create_info.clone()).unwrap(); - let image_views = images - .into_iter() - .map(|image| ImageView::new_default(image).unwrap()) - .collect::>(); + let image_views = images + .into_iter() + .map(|image| ImageView::new_default(image).unwrap()) + .collect::>(); - (swapchain, image_views) - }; + (swapchain, image_views) + }; - render_context - .update_viewport(swapchain_size, scale) - .unwrap(); + render_context + .update_viewport(&mut shared_context, swapchain_size, scale) + .unwrap(); - println!("new swapchain_size: {swapchain_size:?}"); - recreate = false; - window.request_redraw(); - } + println!("new swapchain_size: {swapchain_size:?}"); + recreate = false; + window.request_redraw(); + } - while timestep.on_tick() { - testbed.layout().tick().unwrap(); - } + while timestep.on_tick() { + testbed.layout().tick().unwrap(); + } - testbed - .update( - (swapchain_size[0] as f32 / scale) as _, - (swapchain_size[1] as f32 / scale) as _, - timestep.alpha, - ) - .unwrap(); + testbed + .update( + (swapchain_size[0] as f32 / scale) as _, + (swapchain_size[1] as f32 / scale) as _, + timestep.alpha, + ) + .unwrap(); - if !render_context.dirty && !testbed.layout().check_toggle_needs_redraw() { - // no need to redraw - std::thread::sleep(std::time::Duration::from_millis(5)); // dirty fix to prevent cpu burning precious cycles doing a busy loop - return; - } + if !render_context.dirty && !testbed.layout().check_toggle_needs_redraw() { + // no need to redraw + std::thread::sleep(std::time::Duration::from_millis(5)); // dirty fix to prevent cpu burning precious cycles doing a busy loop + return; + } - log::trace!("drawing frame {}", frame_index); - frame_index += 1; + log::trace!("drawing frame {}", frame_index); + frame_index += 1; - profiler.start(); + profiler.start(); - { - let (image_index, _, acquire_future) = - match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) { - Ok(r) => r, - Err(VulkanError::OutOfDate) => { - recreate = true; - return; - } - Err(e) => panic!("failed to acquire next image: {e}"), - }; + { + let (image_index, _, acquire_future) = match acquire_next_image( + swapchain.clone(), + None, + ) + .map_err(Validated::unwrap) + { + Ok(r) => r, + Err(VulkanError::OutOfDate) => { + recreate = true; + return; + } + Err(e) => panic!("failed to acquire next image: {e}"), + }; - let tgt = images[image_index as usize].clone(); + let tgt = images[image_index as usize].clone(); - last_draw = std::time::Instant::now(); + last_draw = std::time::Instant::now(); - let mut cmd_buf = gfx - .create_gfx_command_buffer(CommandBufferUsage::OneTimeSubmit) - .unwrap(); - cmd_buf.begin_rendering(tgt).unwrap(); + let mut cmd_buf = gfx + .create_gfx_command_buffer(CommandBufferUsage::OneTimeSubmit) + .unwrap(); + cmd_buf.begin_rendering(tgt).unwrap(); - let primitives = wgui::drawing::draw(testbed.layout()).unwrap(); - render_context - .draw(&gfx, &mut cmd_buf, &primitives) - .unwrap(); + let primitives = wgui::drawing::draw(testbed.layout()).unwrap(); + render_context + .draw(&mut shared_context, &mut cmd_buf, &primitives) + .unwrap(); - cmd_buf.end_rendering().unwrap(); + cmd_buf.end_rendering().unwrap(); - let cmd_buf = cmd_buf.build().unwrap(); + let cmd_buf = cmd_buf.build().unwrap(); - acquire_future - .then_execute(gfx.queue_gfx.clone(), cmd_buf) - .unwrap() - .then_swapchain_present( - gfx.queue_gfx.clone(), - SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index), - ) - .then_signal_fence_and_flush() - .unwrap() - .wait(None) - .unwrap(); - } + acquire_future + .then_execute(gfx.queue_gfx.clone(), cmd_buf) + .unwrap() + .then_swapchain_present( + gfx.queue_gfx.clone(), + SwapchainPresentInfo::swapchain_image_index( + swapchain.clone(), + image_index, + ), + ) + .then_signal_fence_and_flush() + .unwrap() + .wait(None) + .unwrap(); + } - profiler.end(); - } - Event::AboutToWait => { - if last_draw.elapsed().as_millis() > 16 { - window.request_redraw(); - } - } - _ => (), - } - })?; + profiler.end(); + } + Event::AboutToWait => { + if last_draw.elapsed().as_millis() > 16 { + window.request_redraw(); + } + } + _ => (), + } + })?; - Ok(()) + Ok(()) } fn swapchain_create_info( - graphics: &WGfx, - format: Format, - surface: Arc, - extent: [u32; 2], + graphics: &WGfx, + format: Format, + surface: Arc, + extent: [u32; 2], ) -> SwapchainCreateInfo { - let surface_capabilities = graphics - .device - .physical_device() - .surface_capabilities(&surface, SurfaceInfo::default()) - .unwrap(); // want panic + let surface_capabilities = graphics + .device + .physical_device() + .surface_capabilities(&surface, SurfaceInfo::default()) + .unwrap(); // want panic - SwapchainCreateInfo { - min_image_count: surface_capabilities.min_image_count.max(2), - image_format: format, - image_extent: extent, - image_usage: ImageUsage::COLOR_ATTACHMENT, - composite_alpha: surface_capabilities - .supported_composite_alpha - .into_iter() - .next() - .unwrap(), // want panic - ..Default::default() - } + SwapchainCreateInfo { + min_image_count: surface_capabilities.min_image_count.max(2), + image_format: format, + image_extent: extent, + image_usage: ImageUsage::COLOR_ATTACHMENT, + composite_alpha: surface_capabilities + .supported_composite_alpha + .into_iter() + .next() + .unwrap(), // want panic + ..Default::default() + } } diff --git a/wgui/src/renderer_vk/context.rs b/wgui/src/renderer_vk/context.rs index e651db2..7bdcd2a 100644 --- a/wgui/src/renderer_vk/context.rs +++ b/wgui/src/renderer_vk/context.rs @@ -2,6 +2,7 @@ use std::{cell::RefCell, rc::Rc, sync::Arc}; use cosmic_text::Buffer; use glam::{Mat4, Vec2, Vec3}; +use slotmap::{SlotMap, new_key_type}; use crate::{ drawing, @@ -70,48 +71,81 @@ impl RendererPass<'_> { } } -pub struct Context { - viewport: Viewport, - text_atlas: TextAtlas, +new_key_type! { + struct SharedContextKey; +} + +pub struct SharedContext { + gfx: Arc, + atlas_map: SlotMap, rect_pipeline: RectPipeline, text_pipeline: TextPipeline, +} + +impl SharedContext { + pub fn new(gfx: Arc) -> anyhow::Result { + let rect_pipeline = RectPipeline::new(gfx.clone(), gfx.surface_format)?; + let text_pipeline = TextPipeline::new(gfx.clone(), gfx.surface_format)?; + + Ok(Self { + gfx, + atlas_map: SlotMap::with_key(), + rect_pipeline, + text_pipeline, + }) + } + + fn atlas_for_pixel_scale(&mut self, pixel_scale: f32) -> anyhow::Result { + for (key, atlas) in self.atlas_map.iter() { + if (atlas.pixel_scale - pixel_scale).abs() < f32::EPSILON { + return Ok(key); + } + } + log::debug!("Initializing SharedAtlas for pixel scale {pixel_scale:.1}"); + let text_atlas = TextAtlas::new(self.text_pipeline.clone())?; + Ok(self.atlas_map.insert(SharedAtlas { + text_atlas, + pixel_scale, + })) + } +} + +pub struct SharedAtlas { + text_atlas: TextAtlas, pixel_scale: f32, +} + +pub struct Context { + viewport: Viewport, + shared_ctx_key: SharedContextKey, pub dirty: bool, + pixel_scale: f32, empty_text: Rc>, } impl Context { - pub fn new( - gfx: Arc, - native_format: vulkano::format::Format, - pixel_scale: f32, - ) -> anyhow::Result { - let rect_pipeline = RectPipeline::new(gfx.clone(), native_format)?; - let text_pipeline = TextPipeline::new(gfx.clone(), native_format)?; - let viewport = Viewport::new(gfx.clone())?; - let text_atlas = TextAtlas::new(text_pipeline.clone())?; + pub fn new(shared: &mut SharedContext, pixel_scale: f32) -> anyhow::Result { + let viewport = Viewport::new(shared.gfx.clone())?; + let shared_ctx_key = shared.atlas_for_pixel_scale(pixel_scale)?; Ok(Self { viewport, - text_atlas, - rect_pipeline, - text_pipeline, + shared_ctx_key, pixel_scale, dirty: true, empty_text: Rc::new(RefCell::new(Buffer::new_empty(DEFAULT_METRICS))), }) } - pub fn regen(&mut self) -> anyhow::Result<()> { - self.text_atlas = TextAtlas::new(self.text_pipeline.clone())?; - self.dirty = true; - Ok(()) - } - - pub fn update_viewport(&mut self, resolution: [u32; 2], pixel_scale: f32) -> anyhow::Result<()> { - if self.pixel_scale != pixel_scale { + pub fn update_viewport( + &mut self, + shared: &mut SharedContext, + resolution: [u32; 2], + pixel_scale: f32, + ) -> anyhow::Result<()> { + if (self.pixel_scale - pixel_scale).abs() < f32::EPSILON { self.pixel_scale = pixel_scale; - self.regen()?; + self.shared_ctx_key = shared.atlas_for_pixel_scale(pixel_scale)?; } if self.viewport.resolution() != resolution { @@ -143,34 +177,20 @@ impl Context { Ok(()) } - fn new_pass(&mut self, passes: &mut Vec) -> anyhow::Result<()> { - passes.push(RendererPass::new( - &mut self.text_atlas, - self.rect_pipeline.clone(), - )?); - - Ok(()) - } - - fn submit_pass( - &mut self, - gfx: &Arc, - cmd_buf: &mut GfxCommandBuffer, - pass: &mut RendererPass, - ) -> anyhow::Result<()> { - pass.submit(gfx, &mut self.viewport, cmd_buf, &mut self.text_atlas)?; - Ok(()) - } - pub fn draw( &mut self, - gfx: &Arc, + shared: &mut SharedContext, cmd_buf: &mut GfxCommandBuffer, primitives: &[drawing::RenderPrimitive], ) -> anyhow::Result<()> { self.dirty = false; - let mut passes = Vec::::new(); - self.new_pass(&mut passes)?; + + let atlas = shared.atlas_map.get_mut(self.shared_ctx_key).unwrap(); + + let mut passes = vec![RendererPass::new( + &mut atlas.text_atlas, + shared.rect_pipeline.clone(), + )?]; for primitive in primitives.iter() { let pass = passes.last_mut().unwrap(); // always safe @@ -214,8 +234,13 @@ impl Context { } let pass = passes.last_mut().unwrap(); - self.submit_pass(gfx, cmd_buf, pass)?; + pass.submit( + &shared.gfx, + &mut self.viewport, + cmd_buf, + &mut atlas.text_atlas, + )?; Ok(()) } -} +} \ No newline at end of file diff --git a/wlx-overlay-s/src/gui/panel.rs b/wlx-overlay-s/src/gui/panel.rs index 963ddd5..93df630 100644 --- a/wlx-overlay-s/src/gui/panel.rs +++ b/wlx-overlay-s/src/gui/panel.rs @@ -33,11 +33,11 @@ pub struct GuiPanel { } impl GuiPanel { - pub fn new_from_template(app: &AppState, path: &str) -> anyhow::Result { + pub fn new_from_template(app: &mut AppState, path: &str) -> anyhow::Result { let (layout, _state) = wgui::parser::new_layout_from_assets(Box::new(gui::asset::GuiAsset {}), path)?; - let context = WguiContext::new(app.gfx.clone(), app.gfx.surface_format, 1.0)?; + let context = WguiContext::new(&mut app.wgui_shared, 1.0)?; let mut timestep = Timestep::new(); timestep.set_tps(60.0); @@ -48,9 +48,9 @@ impl GuiPanel { }) } - pub fn new_blank(app: &AppState) -> anyhow::Result { + pub fn new_blank(app: &mut AppState) -> anyhow::Result { let layout = Layout::new(Box::new(GuiAsset {}))?; - let context = WguiContext::new(app.gfx.clone(), app.gfx.surface_format, 1.0)?; + let context = WguiContext::new(&mut app.wgui_shared, 1.0)?; let mut timestep = Timestep::new(); timestep.set_tps(60.0); @@ -177,7 +177,8 @@ impl OverlayRenderer for GuiPanel { buf: &mut CommandBuffers, _alpha: f32, ) -> anyhow::Result { - self.context.update_viewport(tgt.extent_u32arr(), 1.0)?; + self.context + .update_viewport(&mut app.wgui_shared, tgt.extent_u32arr(), 1.0)?; self.layout.update(MAX_SIZE_VEC2, self.timestep.alpha)?; let mut cmd_buf = app @@ -187,7 +188,8 @@ impl OverlayRenderer for GuiPanel { cmd_buf.begin_rendering(tgt)?; let primitives = wgui::drawing::draw(&self.layout)?; - self.context.draw(&app.gfx, &mut cmd_buf, &primitives)?; + self.context + .draw(&mut app.wgui_shared, &mut cmd_buf, &primitives)?; cmd_buf.end_rendering()?; buf.push(cmd_buf.build()?); diff --git a/wlx-overlay-s/src/overlays/keyboard/builder.rs b/wlx-overlay-s/src/overlays/keyboard/builder.rs index e8ee6a7..007cec0 100644 --- a/wlx-overlay-s/src/overlays/keyboard/builder.rs +++ b/wlx-overlay-s/src/overlays/keyboard/builder.rs @@ -31,7 +31,7 @@ const PIXELS_PER_UNIT: f32 = 80.; #[allow(clippy::too_many_lines, clippy::significant_drop_tightening)] pub fn create_keyboard( - app: &AppState, + app: &mut AppState, mut keymap: Option, ) -> anyhow::Result> where diff --git a/wlx-overlay-s/src/state.rs b/wlx-overlay-s/src/state.rs index 1bcd371..f3e7e73 100644 --- a/wlx-overlay-s/src/state.rs +++ b/wlx-overlay-s/src/state.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; use smallvec::{SmallVec, smallvec}; use std::sync::Arc; use vulkano::image::view::ImageView; -use wgui::gfx::WGfx; +use wgui::{gfx::WGfx, renderer_vk::context::SharedContext as WSharedContext}; #[cfg(feature = "wayvr")] use { @@ -34,6 +34,8 @@ pub struct AppState { pub hid_provider: HidWrapper, pub audio_provider: AudioOutput, + pub wgui_shared: WSharedContext, + pub input_state: InputState, pub screens: SmallVec<[ScreenMeta; 8]>, pub anchor: Affine3A, @@ -71,6 +73,8 @@ impl AppState { include_bytes!("res/557297.wav"), ); + let wgui_shared = WSharedContext::new(gfx.clone())?; + Ok(Self { session, tasks, @@ -78,6 +82,7 @@ impl AppState { gfx_extras, hid_provider: HidWrapper::new(), audio_provider: AudioOutput::new(), + wgui_shared, input_state: InputState::new(), screens: smallvec![], anchor: Affine3A::IDENTITY,