From a3b60b96070b60a34c74342702cf8ee4b478de58 Mon Sep 17 00:00:00 2001 From: galister <22305755+galister@users.noreply.github.com> Date: Thu, 7 Dec 2023 02:07:13 +0100 Subject: [PATCH] screens & basic interactions --- Cargo.lock | 1 - Cargo.toml | 11 +- src/backend/input.rs | 72 +- src/backend/openvr/input.rs | 2 + src/backend/openvr/lines.rs | 130 ++++ src/backend/openvr/mod.rs | 137 ++-- src/backend/openvr/overlay.rs | 41 +- src/backend/overlay.rs | 12 +- src/graphics.rs | 94 +-- src/graphics.rs.bak2 | 1197 --------------------------------- src/gui/font.rs | 5 +- src/gui/mod.rs | 28 +- src/input.rs | 21 +- src/main.rs | 3 +- src/main.rs.bak2 | 159 ----- src/overlays/keyboard.rs | 11 +- src/overlays/screen.rs | 182 ++++- src/overlays/watch.rs | 6 +- src/state.rs | 5 +- 19 files changed, 518 insertions(+), 1599 deletions(-) create mode 100644 src/backend/openvr/lines.rs delete mode 100644 src/graphics.rs.bak2 delete mode 100644 src/main.rs.bak2 diff --git a/Cargo.lock b/Cargo.lock index 641b97b..6dc1b44 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4024,7 +4024,6 @@ dependencies = [ [[package]] name = "wlx-capture" version = "0.1.0" -source = "git+https://github.com/galister/wlx-capture.git#56eba19fac9834e2dfb77dd3a0a93b088a93dee9" dependencies = [ "ashpd", "drm-fourcc", diff --git a/Cargo.toml b/Cargo.toml index 1aa792a..8a79c50 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,12 @@ +[profile.release-with-debug] +inherits = "release" +debuginfo-level = 1 +jemalloc = false +debug = true + +[rust] +debuginfo-level = 1 + [package] name = "wlx-overlay-s" version = "0.1.0" @@ -36,5 +45,5 @@ vulkano-shaders = "0.33.0" vulkano-util = "0.33.0" vulkano-win = "0.33.0" winit = "0.28.6" -wlx-capture = { git = "https://github.com/galister/wlx-capture.git" } +wlx-capture = { path = "../wlx-capture" } diff --git a/src/backend/input.rs b/src/backend/input.rs index 625c718..d566748 100644 --- a/src/backend/input.rs +++ b/src/backend/input.rs @@ -1,7 +1,6 @@ use std::{collections::VecDeque, time::Instant}; use glam::{Affine3A, Vec2, Vec3A}; -use log::warn; use ovr_overlay::TrackedDeviceIndex; use tinyvec::array_vec; @@ -42,6 +41,39 @@ impl InputState { pub fn post_update(&mut self) { for hand in &mut self.pointers { + #[cfg(debug_assertions)] + { + if hand.now.click != hand.before.click { + log::debug!("Hand {}: click {}", hand.idx, hand.now.click); + } + if hand.now.grab != hand.before.grab { + log::debug!("Hand {}: grab {}", hand.idx, hand.now.grab); + } + if hand.now.alt_click != hand.before.alt_click { + log::debug!("Hand {}: alt_click {}", hand.idx, hand.now.alt_click); + } + if hand.now.show_hide != hand.before.show_hide { + log::debug!("Hand {}: show_hide {}", hand.idx, hand.now.show_hide); + } + if hand.now.space_drag != hand.before.space_drag { + log::debug!("Hand {}: space_drag {}", hand.idx, hand.now.space_drag); + } + if hand.now.click_modifier_right != hand.before.click_modifier_right { + log::debug!( + "Hand {}: click_modifier_right {}", + hand.idx, + hand.now.click_modifier_right + ); + } + if hand.now.click_modifier_middle != hand.before.click_modifier_middle { + log::debug!( + "Hand {}: click_modifier_middle {}", + hand.idx, + hand.now.click_modifier_middle + ); + } + } + if hand.now.click_modifier_right { hand.interaction.mode = PointerMode::Right; continue; @@ -176,7 +208,7 @@ pub enum PointerMode { } impl Pointer { - pub fn interact(&mut self, overlays: &mut OverlayContainer, app: &mut AppState) + pub fn interact(&mut self, overlays: &mut OverlayContainer, app: &mut AppState) -> f32 where O: Default, { @@ -184,10 +216,10 @@ impl Pointer { if let Some(grabbed) = overlays.mut_by_id(grab_data.grabbed_id) { self.handle_grabbed(grabbed, grab_data.offset); } else { - warn!("Grabbed overlay {} does not exist", grab_data.grabbed_id); + log::warn!("Grabbed overlay {} does not exist", grab_data.grabbed_id); self.interaction.grabbed = None; } - return; + return grab_data.offset.length(); // grab interaction } let Some(mut hit) = self.get_nearest_hit(overlays) else { @@ -208,7 +240,7 @@ impl Pointer { clicked.backend.on_pointer(app, &hit, false); } } - return; + return 0.0; // no hit }; if let Some(hovered_id) = self.interaction.hovered_id { @@ -222,14 +254,14 @@ impl Pointer { } } let Some(hovered) = overlays.mut_by_id(hit.overlay) else { - warn!("Hit overlay {} does not exist", hit.overlay); - return; + log::warn!("Hit overlay {} does not exist", hit.overlay); + return 0.0; // no hit }; self.interaction.hovered_id = Some(hit.overlay); if let Some(primary_pointer) = hovered.primary_pointer { - if hit.pointer < primary_pointer { + if hit.pointer <= primary_pointer { hovered.primary_pointer = Some(hit.pointer); hit.primary = true; } @@ -237,6 +269,14 @@ impl Pointer { hovered.primary_pointer = Some(hit.pointer); hit.primary = true; } + + log::debug!("Hit: {} {:?}", hovered.state.name, hit); + + if self.now.grab && !self.before.grab { + self.start_grab(hovered); + return hit.dist; + } + hovered.backend.on_hover(app, &hit); if self.now.scroll.abs() > 0.1 { @@ -255,6 +295,7 @@ impl Pointer { hovered.backend.on_pointer(app, &hit, false); } } + hit.dist } fn get_nearest_hit(&mut self, overlays: &mut OverlayContainer) -> Option @@ -276,15 +317,17 @@ impl Pointer { hits.sort_by(|a, b| a.dist.partial_cmp(&b.dist).unwrap()); for hit in hits.iter() { - let uv = overlays - .get_by_id(hit.overlay) - .unwrap() // this is safe + let overlay = overlays.get_by_id(hit.overlay).unwrap(); // this is safe + + let uv = overlay .state .transform .inverse() .transform_point3a(hit.hit_pos) .truncate(); + let uv = overlay.state.interaction_transform.transform_point2(uv); + if uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0 { continue; } @@ -315,7 +358,9 @@ impl Pointer { offset, grabbed_id: overlay.state.id, }); + log::info!("Hand {}: grabbed {}", self.idx, overlay.state.name); } + fn handle_grabbed(&mut self, overlay: &mut OverlayData, offset: Vec3A) where O: Default, @@ -324,7 +369,7 @@ impl Pointer { overlay.state.transform.translation = self.pose.transform_point3a(offset); if self.now.click && !self.before.click { - warn!("todo: click-while-grabbed"); + log::warn!("todo: click-while-grabbed"); } match self.interaction.mode { @@ -339,11 +384,14 @@ impl Pointer { .mul_scalar(1.0 + 0.01 * self.now.scroll); } } + overlay.state.dirty = true; } else { overlay.state.spawn_point = overlay.state.transform.translation; self.interaction.grabbed = None; + log::info!("Hand {}: dropped {}", self.idx, overlay.state.name); } } + fn ray_test(&self, overlay: usize, plane: &Affine3A) -> Option { let plane_normal = plane.transform_vector3a(Vec3A::NEG_Z); let ray_dir = self.pose.transform_vector3a(Vec3A::NEG_Z); diff --git a/src/backend/openvr/input.rs b/src/backend/openvr/input.rs index 5c5509b..fe77599 100644 --- a/src/backend/openvr/input.rs +++ b/src/backend/openvr/input.rs @@ -59,6 +59,7 @@ pub(super) struct OpenVrInputState { } pub(super) struct OpenVrHandState { + pub(super) line_id: usize, has_pose: bool, input_hnd: InputValueHandle, pose_hnd: ActionHandle, @@ -103,6 +104,7 @@ impl InputState { pose: Affine3A::IDENTITY, interaction: InteractionState::default(), data: OpenVrHandState { + line_id: 0, has_pose: false, input_hnd: input_hnd[i], pose_hnd: pose_hnd[i], diff --git a/src/backend/openvr/lines.rs b/src/backend/openvr/lines.rs new file mode 100644 index 0000000..ee2bdb9 --- /dev/null +++ b/src/backend/openvr/lines.rs @@ -0,0 +1,130 @@ +use std::f32::consts::PI; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::Arc; + +use glam::{Affine3A, Vec3, Vec3A, Vec4}; +use idmap::IdMap; +use ovr_overlay::overlay::OverlayManager; +use vulkano::command_buffer::CommandBufferUsage; +use vulkano::format::Format; +use vulkano::image::view::ImageView; +use vulkano::image::{ImageAccess, ImageLayout, ImageViewAbstract, ImmutableImage}; + +use crate::backend::overlay::{OverlayData, OverlayRenderer, OverlayState, SplitOverlayBackend}; +use crate::graphics::WlxGraphics; +use crate::state::AppState; + +use super::overlay::OpenVrOverlayData; + +static AUTO_INCREMENT: AtomicUsize = AtomicUsize::new(1); + +pub(super) struct LinePool { + lines: IdMap>, + view: Arc>, +} + +impl LinePool { + pub fn new(graphics: Arc) -> Self { + let mut command_buffer = graphics.create_command_buffer(CommandBufferUsage::OneTimeSubmit); + + let buf = vec![255; 16]; + + let texture = command_buffer.texture2d(2, 2, Format::R8G8B8A8_UNORM, buf); + command_buffer.build_and_execute_now(); + + graphics + .transition_layout( + texture.inner().image.clone(), + ImageLayout::ShaderReadOnlyOptimal, + ImageLayout::TransferSrcOptimal, + ) + .wait(None) + .unwrap(); + + let view = ImageView::new_default(texture).unwrap(); + + LinePool { + lines: IdMap::new(), + view, + } + } + + pub fn allocate(&mut self, overlay: &mut OverlayManager, app: &mut AppState) -> usize { + let id = AUTO_INCREMENT.fetch_add(1, Ordering::Relaxed); + + let mut data = OverlayData:: { + state: OverlayState { + name: Arc::from(format!("wlx-line{}", id)), + show_hide: true, + width: 0.002, + size: (0, 0), + ..Default::default() + }, + backend: Box::new(SplitOverlayBackend { + renderer: Box::new(StaticRenderer { + view: self.view.clone(), + }), + ..Default::default() + }), + ..Default::default() + }; + data.data.sort_order = 69; + + data.initialize(overlay, app); + data.upload_texture(overlay, &app.graphics); + + self.lines.insert(id, data); + id + } + + pub fn draw_from(&mut self, id: usize, mut from: Affine3A, len: f32, color: Vec4) { + let rotation = Affine3A::from_axis_angle(Vec3::X, -PI * 0.5); + + from.translation = from.translation + from.transform_vector3a(Vec3A::NEG_Z) * (len * 0.5); + let transform = from * rotation * Affine3A::from_scale(Vec3::new(1., len / 0.002, 1.)); + + self.draw_transform(id, transform, color); + } + + fn draw_transform(&mut self, id: usize, transform: Affine3A, color: Vec4) { + if let Some(data) = self.lines.get_mut(id) { + data.state.want_visible = true; + data.state.transform = transform; + data.data.color = color; + } else { + log::warn!("Line {} does not exist", id); + } + } + + pub fn hide(&mut self, id: usize) { + if let Some(data) = self.lines.get_mut(id) { + data.state.want_visible = false; + } else { + log::warn!("Line {} does not exist", id); + } + } + + pub fn update(&mut self, overlay: &mut OverlayManager, app: &mut AppState) { + for data in self.lines.values_mut() { + data.after_input(overlay, app); + if data.state.want_visible { + data.upload_transform(overlay); + data.upload_color(overlay); + } + } + } +} + +struct StaticRenderer { + view: Arc>, +} + +impl OverlayRenderer for StaticRenderer { + fn init(&mut self, _app: &mut AppState) {} + fn pause(&mut self, _app: &mut AppState) {} + fn resume(&mut self, _app: &mut AppState) {} + fn render(&mut self, _app: &mut AppState) {} + fn view(&mut self) -> Option> { + Some(self.view.clone()) + } +} diff --git a/src/backend/openvr/mod.rs b/src/backend/openvr/mod.rs index 73baddd..2a90487 100644 --- a/src/backend/openvr/mod.rs +++ b/src/backend/openvr/mod.rs @@ -1,10 +1,9 @@ +use glam::Vec4; use std::{ collections::VecDeque, - path::Path, time::{Duration, Instant}, }; -use log::{error, info}; use ovr_overlay::{ sys::{ETrackedDeviceProperty, EVRApplicationType, EVREventType}, TrackedDeviceIndex, @@ -15,7 +14,7 @@ use vulkano::{ Handle, VulkanObject, }; -use crate::state::AppState; +use crate::{backend::openvr::lines::LinePool, state::AppState}; use self::{input::action_manifest_path, overlay::OpenVrOverlayData}; @@ -25,12 +24,13 @@ use super::{ }; pub mod input; +pub mod lines; pub mod overlay; pub fn openvr_run() { let app_type = EVRApplicationType::VRApplication_Overlay; let Ok(context) = ovr_overlay::Context::init(app_type) else { - error!("Failed to initialize OpenVR"); + log::error!("Failed to initialize OpenVR"); return; }; @@ -56,12 +56,12 @@ pub fn openvr_run() { let mut overlays = OverlayContainer::::new(&mut state); if let Err(e) = input_mngr.set_action_manifest(action_manifest_path()) { - error!("Failed to set action manifest: {}", e.description()); + log::error!("Failed to set action manifest: {}", e.description()); return; }; let Ok(mut input) = InputState::new(&mut input_mngr) else { - error!("Failed to initialize input"); + log::error!("Failed to initialize input"); return; }; @@ -69,21 +69,25 @@ pub fn openvr_run() { TrackedDeviceIndex::HMD, ETrackedDeviceProperty::Prop_DisplayFrequency_Float, ) else { - error!("Failed to get display refresh rate"); + log::error!("Failed to get display refresh rate"); return; }; - info!("HMD running @ {} Hz", refresh_rate); + log::info!("HMD running @ {} Hz", refresh_rate); let frame_time = (1000.0 / refresh_rate).floor() * 0.001; let mut next_device_update = Instant::now(); let mut due_tasks = VecDeque::with_capacity(4); + let mut lines = LinePool::new(state.graphics.clone()); + input.pointers[0].data.line_id = lines.allocate(&mut overlay_mngr, &mut state); + input.pointers[1].data.line_id = lines.allocate(&mut overlay_mngr, &mut state); + loop { while let Some(event) = system_mngr.poll_next_event() { match event.event_type { EVREventType::VREvent_Quit => { - info!("Received quit event, shutting down."); + log::info!("Received quit event, shutting down."); return; } EVREventType::VREvent_TrackedDeviceActivated @@ -93,64 +97,73 @@ pub fn openvr_run() { } _ => {} } + } - if next_device_update <= Instant::now() { - input.update_devices(&mut system_mngr); - next_device_update = Instant::now() + Duration::from_secs(30); - } + if next_device_update <= Instant::now() { + input.update_devices(&mut system_mngr); + next_device_update = Instant::now() + Duration::from_secs(30); + } - state.tasks.retrieve_due(&mut due_tasks); - while let Some(task) = due_tasks.pop_front() { - match task { - TaskType::Global(f) => f(&mut state), - TaskType::Overlay(sel, f) => { - if let Some(o) = overlays.mut_by_selector(&sel) { - f(&mut state, &mut o.state); - } + state.tasks.retrieve_due(&mut due_tasks); + while let Some(task) = due_tasks.pop_front() { + match task { + TaskType::Global(f) => f(&mut state), + TaskType::Overlay(sel, f) => { + if let Some(o) = overlays.mut_by_selector(&sel) { + f(&mut state, &mut o.state); } } } - - input.pre_update(); - input.update(&mut input_mngr, &mut system_mngr); - input.post_update(); - - input - .pointers - .iter_mut() - .for_each(|p| p.interact(&mut overlays, &mut state)); - - overlays - .iter_mut() - .for_each(|o| o.after_input(&mut overlay_mngr, &mut state)); - - log::debug!("Rendering frame"); - - overlays - .iter_mut() - .filter(|o| o.state.want_visible) - .for_each(|o| o.render(&mut state)); - - log::debug!("Rendering overlays"); - - overlays - .iter_mut() - .for_each(|o| o.after_render(&mut overlay_mngr, &state.graphics)); - - // chaperone - - // close font handles? - - // playspace moved end frame - - let mut seconds_since_vsync = 0f32; - std::thread::sleep(Duration::from_secs_f32( - if system_mngr.get_time_since_last_vsync(&mut seconds_since_vsync, &mut 0u64) { - (frame_time - seconds_since_vsync).max(0.0) - } else { - 0.011 - }, - )); } + + input.pre_update(); + input.update(&mut input_mngr, &mut system_mngr); + input.post_update(); + + input.pointers.iter_mut().for_each(|p| { + let dist = p.interact(&mut overlays, &mut state); + if dist > 0.001 { + lines.draw_from(p.data.line_id, p.pose, dist, Vec4::ONE); + } else { + lines.draw_from(p.data.line_id, p.pose, 20.0, Vec4::ONE); + // lines.hide(p.data.line_id); + } + }); + + lines.update(&mut overlay_mngr, &mut state); + + overlays + .iter_mut() + .for_each(|o| o.after_input(&mut overlay_mngr, &mut state)); + + log::debug!("Rendering frame"); + + overlays + .iter_mut() + .filter(|o| o.state.want_visible) + .for_each(|o| o.render(&mut state)); + + log::debug!("Rendering overlays"); + + overlays + .iter_mut() + .for_each(|o| o.after_render(&mut overlay_mngr, &state.graphics)); + + // chaperone + + // close font handles? + + // playspace moved end frame + + state.input.on_new_frame(); + + let mut seconds_since_vsync = 0f32; + std::thread::sleep(Duration::from_secs_f32( + if system_mngr.get_time_since_last_vsync(&mut seconds_since_vsync, &mut 0u64) { + frame_time - (seconds_since_vsync % frame_time) + } else { + frame_time + }, + )); } } diff --git a/src/backend/openvr/overlay.rs b/src/backend/openvr/overlay.rs index b5cf42c..2638a51 100644 --- a/src/backend/openvr/overlay.rs +++ b/src/backend/openvr/overlay.rs @@ -6,7 +6,11 @@ use ovr_overlay::{ }; use vulkano::{image::ImageAccess, Handle, VulkanObject}; -use crate::{backend::overlay::OverlayData, graphics::WlxGraphics, state::AppState}; +use crate::{ + backend::overlay::{OverlayData, RelativeTo}, + graphics::WlxGraphics, + state::AppState, +}; #[derive(Default)] pub(super) struct OpenVrOverlayData { @@ -16,10 +20,11 @@ pub(super) struct OpenVrOverlayData { pub(super) color: Vec4, pub(super) curvature: f32, pub(super) sort_order: u32, + pub(super) relative_to: RelativeTo, } impl OverlayData { - pub fn initialize( + pub(super) fn initialize( &mut self, overlay: &mut OverlayManager, app: &mut AppState, @@ -33,6 +38,11 @@ impl OverlayData { }; log::debug!("{}: initialize", self.state.name); + //watch + if self.state.id == 0 { + self.data.sort_order = 68; + } + self.data.handle = Some(handle); self.data.color = Vec4::ONE; @@ -41,11 +51,12 @@ impl OverlayData { self.upload_width(overlay); self.upload_color(overlay); self.upload_curvature(overlay); + self.upload_sort_order(overlay); handle } - pub fn after_input(&mut self, overlay: &mut OverlayManager, app: &mut AppState) { + pub(super) fn after_input(&mut self, overlay: &mut OverlayManager, app: &mut AppState) { if self.state.want_visible && !self.data.visible { self.show(overlay, app); } else if !self.state.want_visible && self.data.visible { @@ -53,9 +64,12 @@ impl OverlayData { } } - pub fn after_render(&mut self, overlay: &mut OverlayManager, graphics: &WlxGraphics) { + pub(super) fn after_render(&mut self, overlay: &mut OverlayManager, graphics: &WlxGraphics) { if self.data.visible { - self.upload_transform(overlay); + if self.state.dirty { + self.upload_transform(overlay); + self.state.dirty = false; + } self.upload_texture(overlay, graphics); } } @@ -83,7 +97,7 @@ impl OverlayData { self.data.visible = false; } - fn upload_color(&self, overlay: &mut OverlayManager) { + pub(super) fn upload_color(&self, overlay: &mut OverlayManager) { let Some(handle) = self.data.handle else { log::debug!("{}: No overlay handle", self.state.name); return; @@ -104,7 +118,7 @@ impl OverlayData { } } - fn upload_width(&self, overlay: &mut OverlayManager) { + pub(super) fn upload_width(&self, overlay: &mut OverlayManager) { let Some(handle) = self.data.handle else { log::debug!("{}: No overlay handle", self.state.name); return; @@ -134,7 +148,7 @@ impl OverlayData { } } - fn upload_transform(&self, overlay: &mut OverlayManager) { + pub(super) fn upload_transform(&self, overlay: &mut OverlayManager) { let Some(handle) = self.data.handle else { log::debug!("{}: No overlay handle", self.state.name); return; @@ -170,7 +184,7 @@ impl OverlayData { } } - fn upload_texture(&mut self, overlay: &mut OverlayManager, graphics: &WlxGraphics) { + pub(super) fn upload_texture(&mut self, overlay: &mut OverlayManager, graphics: &WlxGraphics) { let Some(handle) = self.data.handle else { log::debug!("{}: No overlay handle", self.state.name); return; @@ -210,8 +224,13 @@ impl OverlayData { m_nQueueFamilyIndex: graphics.queue.queue_family_index(), }; - log::info!("Usages: {:?}", image.usage()); - log::info!("nImage: {}, nFormat: {:?}, nWidth: {}, nHeight: {}, nSampleCount: {}, nQueueFamilyIndex: {}", texture.m_nImage, format, texture.m_nWidth, texture.m_nHeight, texture.m_nSampleCount, texture.m_nQueueFamilyIndex); + log::debug!( + "UploadTex: {:?}, {}x{}, {:?}", + format, + texture.m_nWidth, + texture.m_nHeight, + image.usage() + ); if let Err(e) = overlay.set_image_vulkan(handle, &mut texture) { panic!("Failed to set overlay texture: {}", e); } diff --git a/src/backend/overlay.rs b/src/backend/overlay.rs index d094e45..006e76c 100644 --- a/src/backend/overlay.rs +++ b/src/backend/overlay.rs @@ -3,7 +3,7 @@ use std::sync::{ Arc, }; -use glam::{Affine3A, Quat, Vec3A}; +use glam::{Affine2, Affine3A, Quat, Vec3A}; use vulkano::image::ImageViewAbstract; use crate::state::AppState; @@ -22,12 +22,13 @@ pub struct OverlayState { pub want_visible: bool, pub show_hide: bool, pub grabbable: bool, + pub dirty: bool, pub transform: Affine3A, pub spawn_point: Vec3A, pub spawn_rotation: Quat, pub relative_to: RelativeTo, pub primary_pointer: Option, - pub interaction_transform: Affine3A, + pub interaction_transform: Affine2, } impl Default for OverlayState { @@ -40,12 +41,13 @@ impl Default for OverlayState { want_visible: false, show_hide: false, grabbable: false, + dirty: false, relative_to: RelativeTo::None, spawn_point: Vec3A::NEG_Z, spawn_rotation: Quat::IDENTITY, transform: Affine3A::IDENTITY, primary_pointer: None, - interaction_transform: Affine3A::IDENTITY, + interaction_transform: Affine2::IDENTITY, } } } @@ -111,12 +113,14 @@ impl OverlayRenderer for FallbackRenderer { fn resume(&mut self, _app: &mut AppState) {} fn render(&mut self, _app: &mut AppState) {} fn view(&mut self) -> Option> { - unimplemented!() + None } } // Boilerplate and dummies +#[derive(Clone, Copy, Debug, Default)] pub enum RelativeTo { + #[default] None, Head, Hand(usize), diff --git a/src/graphics.rs b/src/graphics.rs index adb1495..b43bf61 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -1,7 +1,6 @@ use std::{error::Error, io::Cursor, slice::Iter, sync::Arc}; use ash::vk::SubmitInfo; -use log::{debug, error, info}; use smallvec::smallvec; use vulkano::{ buffer::{ @@ -28,9 +27,9 @@ use vulkano::{ }, format::Format, image::{ - sys::Image, AttachmentImage, ImageAccess, ImageCreateFlags, ImageDimensions, ImageError, - ImageLayout, ImageUsage, ImageViewAbstract, ImmutableImage, MipmapsCount, StorageImage, - SubresourceData, SwapchainImage, + sys::Image, AttachmentImage, ImageCreateFlags, ImageDimensions, ImageError, ImageLayout, + ImageUsage, ImageViewAbstract, ImmutableImage, MipmapsCount, StorageImage, SubresourceData, + SwapchainImage, }, instance::{Instance, InstanceCreateInfo, InstanceExtensions}, memory::allocator::{AllocationCreateInfo, MemoryUsage, StandardMemoryAllocator}, @@ -49,8 +48,8 @@ use vulkano::{ shader::ShaderModule, swapchain::{CompositeAlpha, Surface, Swapchain, SwapchainCreateInfo}, sync::{ - fence::Fence, future::NowFuture, AccessFlags, DependencyInfo, ImageMemoryBarrier, - PipelineStages, + fence::Fence, future::NowFuture, AccessFlags, DependencyInfo, GpuFuture, + ImageMemoryBarrier, PipelineStages, }, Version, VulkanLibrary, VulkanObject, }; @@ -103,8 +102,8 @@ impl WlxGraphics { let library_extensions = vulkano_win::required_extensions(&library); let required_extensions = library_extensions.union(&vk_instance_extensions); - debug!("Instance exts for app: {:?}", &required_extensions); - debug!("Instance exts for runtime: {:?}", &vk_instance_extensions); + log::debug!("Instance exts for app: {:?}", &required_extensions); + log::debug!("Instance exts for runtime: {:?}", &vk_instance_extensions); let instance = Instance::new( library, @@ -126,7 +125,7 @@ impl WlxGraphics { ..DeviceExtensions::empty() }; - debug!("Device exts for app: {:?}", &device_extensions); + log::debug!("Device exts for app: {:?}", &device_extensions); // TODO headless let event_loop = EventLoop::new(); @@ -142,7 +141,7 @@ impl WlxGraphics { }) .filter_map(|p| { let runtime_extensions = vk_device_extensions_fn(&p); - debug!( + log::debug!( "Device exts for {}: {:?}", p.properties().device_name, &runtime_extensions @@ -174,7 +173,7 @@ impl WlxGraphics { }) .expect("no suitable physical device found"); - info!( + log::info!( "Using vkPhysicalDevice: {}", physical_device.properties().device_name, ); @@ -271,6 +270,7 @@ impl WlxGraphics { (Arc::new(me), event_loop) } + #[allow(dead_code)] pub fn create_swapchain( &self, format: Option, @@ -541,32 +541,7 @@ pub struct WlxCommandBuffer { } impl WlxCommandBuffer { - pub fn inner(&self) -> &AutoCommandBufferBuilder> { - &self.command_buffer - } - - pub fn inner_mut( - &mut self, - ) -> &mut AutoCommandBufferBuilder> { - &mut self.command_buffer - } - - pub fn to_inner(self) -> AutoCommandBufferBuilder> { - self.command_buffer - } - - pub fn begin( - mut self, - render_target: Arc, - want_layout: Option, - ) -> Self { - if let Some(want_layout) = want_layout { - let mut barrier = - ImageMemoryBarrier::image(render_target.image().inner().image.clone()); - barrier.old_layout = ImageLayout::ColorAttachmentOptimal; - barrier.new_layout = want_layout; - } - + pub fn begin(mut self, render_target: Arc) -> Self { self.command_buffer .begin_rendering(RenderingInfo { contents: SubpassContents::SecondaryCommandBuffers, @@ -590,13 +565,6 @@ impl WlxCommandBuffer { self } - pub fn run(mut self, pass: &WlxPass) -> Self { - let _ = self - .command_buffer - .execute_commands(pass.command_buffer.clone()); - self - } - pub fn texture2d( &mut self, width: u32, @@ -614,13 +582,14 @@ impl WlxCommandBuffer { &self.graphics.memory_allocator, data, dimensions, - MipmapsCount::One, + MipmapsCount::Log2, // required for TRANSFER_SRC format, &mut self.command_buffer, ) .unwrap() } + #[allow(dead_code)] pub fn texture2d_png(&mut self, bytes: Vec) -> Arc { let cursor = Cursor::new(bytes); let decoder = png::Decoder::new(cursor); @@ -636,32 +605,24 @@ impl WlxCommandBuffer { } impl WlxCommandBuffer { - pub fn end_render_and_continue(&mut self) { + pub fn end_render(mut self) -> Self { self.command_buffer.end_rendering().unwrap(); + self } - pub fn end_render(self) -> PrimaryAutoCommandBuffer { - let mut buf = self.command_buffer; - buf.end_rendering().unwrap(); - - buf.build().unwrap() - } - - pub fn end(self) -> PrimaryAutoCommandBuffer { + pub fn build(self) -> PrimaryAutoCommandBuffer { self.command_buffer.build().unwrap() } - pub fn end_render_and_execute(self) -> CommandBufferExecFuture { - let mut buf = self.command_buffer; - buf.end_rendering().unwrap(); - let buf = buf.build().unwrap(); - buf.execute(self.graphics.queue.clone()).unwrap() + pub fn build_and_execute(self) -> CommandBufferExecFuture { + let queue = self.graphics.queue.clone(); + self.build().execute(queue).unwrap() } - pub fn end_and_execute(self) -> CommandBufferExecFuture { - let buf = self.command_buffer; - let buf = buf.build().unwrap(); - buf.execute(self.graphics.queue.clone()).unwrap() + pub fn build_and_execute_now(self) { + let mut exec = self.build_and_execute(); + exec.flush().unwrap(); + exec.cleanup_finished(); } } @@ -705,10 +666,6 @@ impl WlxPipeline { self.pipeline.clone() } - pub fn graphics(&self) -> Arc { - self.graphics.clone() - } - pub fn uniform_sampler( &self, set: usize, @@ -780,6 +737,7 @@ impl WlxPipeline { } } +#[allow(dead_code)] pub struct WlxPass { pipeline: Arc, vertex_buffer: Subbuffer<[Vert2Uv]>, @@ -833,7 +791,7 @@ impl WlxPass { .draw_indexed(index_buffer.len() as u32, 1, 0, 0, 0) .or_else(|err| { if let Some(source) = err.source() { - error!("Failed to draw: {}", source); + log::error!("Failed to draw: {}", source); } Err(err) }) diff --git a/src/graphics.rs.bak2 b/src/graphics.rs.bak2 deleted file mode 100644 index c2be221..0000000 --- a/src/graphics.rs.bak2 +++ /dev/null @@ -1,1197 +0,0 @@ -use core::slice; -use std::{sync::Arc, slice::Iter, io::Cursor, error::Error, borrow::{Cow, BorrowMut}, cell::RefCell, fs::File, os::fd::{FromRawFd, IntoRawFd}, mem}; - -use ash::{extensions::{ - ext::DebugUtils, - khr::{Surface,Swapchain, self}, -}, util::Align}; - -use ash::vk; -use cstr::cstr; -use glam::f32::Vec4; -use libc::c_char; -use log::{info,error}; -use raw_window_handle::*; -use smallvec::smallvec; -use std::env; -use std::ffi::CStr; -use winit::{event_loop::{EventLoop, self, ControlFlow}, window::{WindowBuilder, Window}, event::{WindowEvent, KeyboardInput, ElementState, VirtualKeyCode, Event}, platform::run_return::EventLoopExtRunReturn}; -use wlx_capture::frame::{DmabufFrame, DRM_FORMAT_ABGR8888, DRM_FORMAT_XBGR8888, DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888}; - -#[repr(C)] -#[derive(Copy, Clone, Debug)] -pub struct Vertex { - pub in_pos: Vec4, - pub in_uv: Vec4, -} - -const APP_NAME: &str = env!("CARGO_PKG_NAME"); -pub const INDICES : [u16; 6] = [2, 1, 0, 1, 2, 3]; - -pub const VERTICES : [Vertex; 4] = [ - Vertex{ in_pos: Vec4::new(0.0, 0.0, 0.0, 0.0), in_uv: Vec4::new(0.0, 0.0, 0.0, 0.0) }, - Vertex{ in_pos: Vec4::new(0.0, 1.0, 0.0, 0.0), in_uv: Vec4::new(0.0, 1.0, 0.0, 0.0) }, - Vertex{ in_pos: Vec4::new(1.0, 0.0, 0.0, 0.0), in_uv: Vec4::new(1.0, 0.0, 0.0, 0.0) }, - Vertex{ in_pos: Vec4::new(1.0, 1.0, 0.0, 0.0), in_uv: Vec4::new(1.0, 1.0, 0.0, 0.0) }, - ]; - -// Simple offset_of macro akin to C++ offsetof -#[macro_export] -macro_rules! offset_of { - ($base:path, $field:ident) => {{ - #[allow(unused_unsafe)] - unsafe { - let b: $base = mem::zeroed(); - std::ptr::addr_of!(b.$field) as isize - std::ptr::addr_of!(b) as isize - } - }}; -} - -pub struct VkGraphics { - pub event_loop: RefCell>, - pub entry: ash::Entry, - - pub instance: ash::Instance, - pub device: ash::Device, - - pub surface_loader: Surface, - pub swapchain_loader: Swapchain, - pub window: winit::window::Window, - - pub device_properies: vk::PhysicalDeviceProperties, - pub device_memory_properties: vk::PhysicalDeviceMemoryProperties, - pub queue_family_index: u32, - pub present_queue: vk::Queue, - - pub surface: vk::SurfaceKHR, - pub surface_format: vk::SurfaceFormatKHR, - pub surface_resolution: vk::Extent2D, - - pub swapchain: vk::SwapchainKHR, - pub swapchain_format: vk::Format, - pub present_images: Vec, - pub present_image_views: Vec, - - pub pool: vk::CommandPool, - pub draw_command_buffer: vk::CommandBuffer, - pub setup_command_buffer: vk::CommandBuffer, - - pub draw_commands_reuse_fence: vk::Fence, - pub setup_commands_reuse_fence: vk::Fence, - - #[cfg(debug_assertions)] - pub debug_utils_loader: DebugUtils, - #[cfg(debug_assertions)] - pub debug_call_back: vk::DebugUtilsMessengerEXT, -} - -impl VkGraphics { - pub fn new() -> Arc { - unsafe { - let window_size = [1920, 1080]; - - let event_loop = EventLoop::new(); - let window = WindowBuilder::new() - .with_title("Vulkan") - .with_inner_size(winit::dpi::LogicalSize::new( - window_size[0], - window_size[1], - )) - .build(&event_loop) - .unwrap(); - - let entry = ash::Entry::load().unwrap(); - let app_name = cstr!(APP_NAME); - let layer_names = [ - #[cfg(debug_assertions)] - cstr!("VK_LAYER_KHRONOS_validation"), - ]; - let layers_names_raw: Vec<*const c_char> = layer_names - .iter() - .map(|raw_name| raw_name.as_ptr()) - .collect(); - - let mut extension_names = ash_window::enumerate_required_extensions(window.raw_display_handle()) - .unwrap() - .to_vec(); - - #[cfg(debug_assertions)] - extension_names.push(DebugUtils::name().as_ptr()); - - let appinfo = vk::ApplicationInfo::builder() - .application_name(app_name) - .application_version(0) - .engine_name(app_name) - .engine_version(0) - .api_version(vk::make_api_version(0, 1, 3, 0)); - - let create_info = vk::InstanceCreateInfo::builder() - .application_info(&appinfo) - .enabled_layer_names(&layers_names_raw) - .enabled_extension_names(&extension_names) - .flags(vk::InstanceCreateFlags::default()); - - let instance: ash::Instance = entry - .create_instance(&create_info, None) - .expect("Could not create Vulkan instance."); - - #[cfg(debug_assertions)] - let (debug_utils_loader, debug_call_back) = - { - let loader = DebugUtils::new(&entry, &instance); - let info = vk::DebugUtilsMessengerCreateInfoEXT::builder() - .message_severity( - vk::DebugUtilsMessageSeverityFlagsEXT::ERROR - | vk::DebugUtilsMessageSeverityFlagsEXT::WARNING - | vk::DebugUtilsMessageSeverityFlagsEXT::INFO - | vk::DebugUtilsMessageSeverityFlagsEXT::VERBOSE, - ) - .message_type( - vk::DebugUtilsMessageTypeFlagsEXT::GENERAL - | vk::DebugUtilsMessageTypeFlagsEXT::VALIDATION - | vk::DebugUtilsMessageTypeFlagsEXT::PERFORMANCE, - ) - .pfn_user_callback(Some(vulkan_debug_callback)) - .build(); - - let callback = loader - .create_debug_utils_messenger(&info, None) - .unwrap(); - (loader, callback) - }; - - let surface = ash_window::create_surface( - &entry, - &instance, - window.raw_display_handle(), - window.raw_window_handle(), - None, - ) - .unwrap(); - - let surface_loader = Surface::new(&entry, &instance); - - let pdevices = instance - .enumerate_physical_devices() - .expect("Physical device error"); - - let (pdevice, queue_family_index) = pdevices - .iter() - .find_map(|pdevice| { - instance - .get_physical_device_queue_family_properties(*pdevice) - .iter() - .enumerate() - .find_map(|(index, info)| { - let supports_graphic_and_surface = - info.queue_flags.contains(vk::QueueFlags::GRAPHICS) - && surface_loader - .get_physical_device_surface_support( - *pdevice, - index as u32, - surface, - ) - .unwrap(); - if supports_graphic_and_surface { - Some((*pdevice, index)) - } else { - None - } - }) - }) - .expect("Couldn't find suitable device."); - - let queue_family_index = queue_family_index as u32; - let device_extension_names_raw = [ - Swapchain::name().as_ptr(), - vk::KhrExternalMemoryFn::name().as_ptr(), - vk::KhrExternalMemoryFdFn::name().as_ptr(), - vk::ExtExternalMemoryDmaBufFn::name().as_ptr(), - vk::ExtImageDrmFormatModifierFn::name().as_ptr(), - ]; - - let priorities = [1.0]; - - let queue_info = vk::DeviceQueueCreateInfo::builder() - .queue_family_index(queue_family_index) - .queue_priorities(&priorities); - - let physical_device_features = vk::PhysicalDeviceFeatures::builder().shader_clip_distance(true).build(); - let mut physical_device_vulkan_13_features = vk::PhysicalDeviceVulkan13Features::builder().dynamic_rendering(true).synchronization2(true).build(); - - let mut features = vk::PhysicalDeviceFeatures2::builder() - .features(physical_device_features) - .push_next(&mut physical_device_vulkan_13_features) - .build(); - - let device_create_info = vk::DeviceCreateInfo::builder() - .queue_create_infos(std::slice::from_ref(&queue_info)) - .enabled_extension_names(&device_extension_names_raw) - .push_next(&mut features); - - let device: ash::Device = instance - .create_device(pdevice, &device_create_info, None) - .unwrap(); - - let present_queue = device.get_device_queue(queue_family_index, 0); - - let surface_format = surface_loader - .get_physical_device_surface_formats(pdevice, surface) - .unwrap()[0]; - - let surface_capabilities = surface_loader - .get_physical_device_surface_capabilities(pdevice, surface) - .unwrap(); - - let desired_image_count = surface_capabilities.min_image_count; - let surface_resolution = match surface_capabilities.current_extent.width { - std::u32::MAX => vk::Extent2D { - width: window_size[0], - height: window_size[1], - }, - _ => surface_capabilities.current_extent, - }; - - let pre_transform = if surface_capabilities - .supported_transforms - .contains(vk::SurfaceTransformFlagsKHR::IDENTITY) - { - vk::SurfaceTransformFlagsKHR::IDENTITY - } else { - surface_capabilities.current_transform - }; - let present_modes = surface_loader - .get_physical_device_surface_present_modes(pdevice, surface) - .unwrap(); - let present_mode = present_modes - .iter() - .cloned() - .find(|&mode| mode == vk::PresentModeKHR::MAILBOX) - .unwrap_or(vk::PresentModeKHR::FIFO); - - let swapchain_loader = Swapchain::new(&instance, &device); - - #[allow(unused)] - let dmabuf_loader = vk::ExtImageDrmFormatModifierFn::load(|name| { - std::mem::transmute(instance.get_device_proc_addr(device.handle(), name.as_ptr())) - }); - - let swapchain_create_info = vk::SwapchainCreateInfoKHR::builder() - .surface(surface) - .min_image_count(desired_image_count) - .image_color_space(surface_format.color_space) - .image_format(surface_format.format) - .image_extent(surface_resolution) - .image_usage(vk::ImageUsageFlags::COLOR_ATTACHMENT) - .image_sharing_mode(vk::SharingMode::EXCLUSIVE) - .pre_transform(pre_transform) - .composite_alpha(vk::CompositeAlphaFlagsKHR::OPAQUE) - .present_mode(present_mode) - .clipped(true) - .image_array_layers(1); - - let swapchain = swapchain_loader - .create_swapchain(&swapchain_create_info, None) - .unwrap(); - - let pool_create_info = vk::CommandPoolCreateInfo::builder() - .flags(vk::CommandPoolCreateFlags::RESET_COMMAND_BUFFER) - .queue_family_index(queue_family_index); - - let pool = device.create_command_pool(&pool_create_info, None).unwrap(); - - let command_buffer_allocate_info = vk::CommandBufferAllocateInfo::builder() - .command_buffer_count(2) - .command_pool(pool) - .level(vk::CommandBufferLevel::PRIMARY); - - let command_buffers = device - .allocate_command_buffers(&command_buffer_allocate_info) - .unwrap(); - - let setup_command_buffer = command_buffers[0]; - let draw_command_buffer = command_buffers[1]; - - let present_images = swapchain_loader.get_swapchain_images(swapchain).unwrap(); - let present_image_views: Vec = present_images - .iter() - .map(|&image| { - let create_view_info = vk::ImageViewCreateInfo::builder() - .view_type(vk::ImageViewType::TYPE_2D) - .format(surface_format.format) - .components(vk::ComponentMapping { - r: vk::ComponentSwizzle::R, - g: vk::ComponentSwizzle::G, - b: vk::ComponentSwizzle::B, - a: vk::ComponentSwizzle::A, - }) - .subresource_range(vk::ImageSubresourceRange { - aspect_mask: vk::ImageAspectFlags::COLOR, - base_mip_level: 0, - level_count: 1, - base_array_layer: 0, - layer_count: 1, - }) - .image(image); - device.create_image_view(&create_view_info, None).unwrap() - }) - .collect(); - let device_memory_properties = instance.get_physical_device_memory_properties(pdevice); - - let device_properies = instance.get_physical_device_properties(pdevice); - - let fence_create_info = - vk::FenceCreateInfo::builder().flags(vk::FenceCreateFlags::SIGNALED); - - let draw_commands_reuse_fence = device - .create_fence(&fence_create_info, None) - .expect("Create fence failed."); - let setup_commands_reuse_fence = device - .create_fence(&fence_create_info, None) - .expect("Create fence failed."); - - let me = Self { - event_loop: RefCell::new(event_loop), - entry, - instance, - device, - queue_family_index, - device_properies, - device_memory_properties, - window, - surface_loader, - surface_format, - present_queue, - surface_resolution, - swapchain_loader, - swapchain, - swapchain_format: surface_format.format, - present_images, - present_image_views, - pool, - draw_command_buffer, - setup_command_buffer, - draw_commands_reuse_fence, - setup_commands_reuse_fence, - surface, - #[cfg(debug_assertions)] - debug_call_back, - #[cfg(debug_assertions)] - debug_utils_loader, - }; - Arc::new(me) - } - } - - pub fn render_loop(&self, f: F) { - self.event_loop - .borrow_mut() - .run_return(|event, _, control_flow| { - *control_flow = ControlFlow::Poll; - match event { - Event::WindowEvent { - event: - WindowEvent::CloseRequested - | WindowEvent::KeyboardInput { - input: - KeyboardInput { - state: ElementState::Pressed, - virtual_keycode: Some(VirtualKeyCode::Escape), - .. - }, - .. - }, - .. - } => *control_flow = ControlFlow::Exit, - Event::MainEventsCleared => f(), - _ => (), - } - }); - } - - pub fn create_frame(self: &Arc) -> VkFrame { - VkFrame::new(self.clone()) - } - - pub fn create_shader(self: &Arc, spv_bytes: &[u8], descriptor_types: Option>) -> Arc { - VkShader::new(self.clone(), spv_bytes, descriptor_types) - } - - pub fn create_pipeline(self: &Arc, vert: Arc, frag: Arc, format: vk::Format) -> VkPipeline { - VkPipeline::new(self.clone(), vert, frag, format) - } - - pub fn create_buffer(self: &Arc, usage: vk::BufferUsageFlags, data: &[T]) -> Arc - where T: Copy { - VkBuffer::new(self.clone(), usage, data) - } -} - -impl Drop for VkGraphics { - fn drop(&mut self) { - unsafe { - self.device.device_wait_idle().unwrap(); - self.device - .destroy_fence(self.draw_commands_reuse_fence, None); - self.device - .destroy_fence(self.setup_commands_reuse_fence, None); - for &image_view in self.present_image_views.iter() { - self.device.destroy_image_view(image_view, None); - } - self.device.destroy_command_pool(self.pool, None); - self.swapchain_loader - .destroy_swapchain(self.swapchain, None); - self.surface_loader.destroy_surface(self.surface, None); - self.debug_utils_loader - .destroy_debug_utils_messenger(self.debug_call_back, None); - self.instance.destroy_instance(None); - self.device.destroy_device(None); - } - } -} - -pub struct VkFrame { - pub graphics: Arc, - - pub command_pool: vk::CommandPool, - pub command_buffer: vk::CommandBuffer, - - pub present_semaphore: vk::Semaphore, - pub render_semaphore: vk::Semaphore, - - pub fence: vk::Fence, -} - -impl VkFrame { - pub fn new(graphics: Arc) -> Self { - let command_pool = unsafe { graphics.device.create_command_pool(&vk::CommandPoolCreateInfo::default(), None) }.unwrap(); - let command_buffer = unsafe { graphics.device.allocate_command_buffers(&vk::CommandBufferAllocateInfo::builder().command_pool(command_pool).command_buffer_count(1).build()) }.unwrap()[0]; - let present_semaphore = unsafe { graphics.device.create_semaphore(&vk::SemaphoreCreateInfo::default(), None) }.unwrap(); - let render_semaphore = unsafe { graphics.device.create_semaphore(&vk::SemaphoreCreateInfo::default(), None) }.unwrap(); - let fence = unsafe { graphics.device.create_fence(&vk::FenceCreateInfo::builder().flags(vk::FenceCreateFlags::SIGNALED).build(), None) }.unwrap(); - - Self { - graphics, - command_pool, - command_buffer, - present_semaphore, - render_semaphore, - fence, - } - } -} - -impl Drop for VkFrame { - fn drop(&mut self) { - unsafe { - self.graphics.device.destroy_command_pool(self.command_pool, None); - self.graphics - .device - .destroy_semaphore(self.present_semaphore, None); - self.graphics - .device - .destroy_semaphore(self.render_semaphore, None); - self.graphics.device.destroy_fence(self.fence, None); - } - } -} - -pub struct VkBuffer { - pub graphics: Arc, - pub buffer: vk::Buffer, - pub memory: vk::DeviceMemory, -} - -impl VkBuffer -{ - pub fn new(graphics: Arc, usage: vk::BufferUsageFlags, data: &[T]) -> Arc - where T: Copy - { - unsafe { - let buffer_size = std::mem::size_of::() * data.len(); - - let buffer_create_info = vk::BufferCreateInfo::builder() - .size(buffer_size as _) - .usage(usage) - .sharing_mode(vk::SharingMode::EXCLUSIVE); - - let buffer = graphics.device.create_buffer(&buffer_create_info, None).unwrap(); - - let memory_req = graphics.device.get_buffer_memory_requirements(buffer); - - let memory_index = find_memorytype_index( - &memory_req, - &graphics.device_memory_properties, - vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT, - ) - .expect("Unable to find suitable memory index for vertex buffer."); - - let memory_allocate_info = vk::MemoryAllocateInfo::builder() - .allocation_size(memory_req.size) - .memory_type_index(memory_index) - .build(); - - let memory = graphics - .device - .allocate_memory(&memory_allocate_info, None) - .unwrap(); - - let memory_ptr = graphics - .device - .map_memory(memory, 0, memory_req.size, vk::MemoryMapFlags::empty()) - .unwrap(); - - let mut slice = Align::::new(memory_ptr, std::mem::align_of::() as _, memory_req.size); - slice.copy_from_slice(data); - - graphics.device.unmap_memory(memory); - graphics.device.bind_buffer_memory(buffer, memory, 0).unwrap(); - - Arc::new(Self { - graphics, - buffer, - memory, - }) - } - } -} - -impl Drop for VkBuffer{ - fn drop(&mut self) { - unsafe { - self.graphics.device.free_memory(self.memory, None); - self.graphics.device.destroy_buffer(self.buffer, None); - } - } -} - -pub struct VkImage { - pub graphics: Arc, - pub image: vk::Image, - pub memory: vk::DeviceMemory, - pub view: Option, - pub sampler: Option, - pub buffer: Option>, -} - -impl VkImage { - pub fn new_empty(graphics: Arc, width: u32, height: u32) -> Self { - todo!(); - } - - pub fn new_from_bytes(&self, graphics: Arc, width: u32, height: u32, format: vk::Format, data: &[u8]) -> Self { - let image_extent = vk::Extent3D { width, height, depth: 1 }; - let image = { - let image_create_info = vk::ImageCreateInfo::builder() - .image_type(vk::ImageType::TYPE_2D) - .format(vk::Format::R8G8B8A8_UNORM) - .extent(image_extent) - .mip_levels(1) - .array_layers(1) - .samples(vk::SampleCountFlags::TYPE_1) - .tiling(vk::ImageTiling::OPTIMAL) - .usage(vk::ImageUsageFlags::TRANSFER_DST - | vk::ImageUsageFlags::TRANSFER_SRC - | vk::ImageUsageFlags::SAMPLED) - .sharing_mode(vk::SharingMode::EXCLUSIVE); - - unsafe { graphics.device.create_image(&image_create_info, None).unwrap() } - }; - - let image_buffer = VkBuffer::new(graphics.clone(), vk::BufferUsageFlags::TRANSFER_SRC, data); - let memory_requirements = unsafe { graphics.device.get_image_memory_requirements(image) }; - let memory_type_index = find_memorytype_index( - &memory_requirements, - &graphics.device_memory_properties, - vk::MemoryPropertyFlags::DEVICE_LOCAL, - ).unwrap(); - - let memory = { - let alloc_info = vk::MemoryAllocateInfo::builder() - .allocation_size(memory_requirements.size) - .memory_type_index(memory_type_index) - .build(); - - unsafe { graphics.device.allocate_memory(&alloc_info, None).unwrap() } - }; - - unsafe { graphics.device.bind_image_memory(image, memory, 0).unwrap() }; - - record_submit_commandbuffer( - &graphics.device, - graphics.setup_command_buffer, - graphics.setup_commands_reuse_fence, - graphics.present_queue, - &[], - &[], - &[], - |device, texture_command_buffer| { - let barrier = vk::ImageMemoryBarrier { - dst_access_mask: vk::AccessFlags::TRANSFER_WRITE, - new_layout: vk::ImageLayout::TRANSFER_DST_OPTIMAL, - image, - subresource_range: vk::ImageSubresourceRange { - aspect_mask: vk::ImageAspectFlags::COLOR, - level_count: 1, - layer_count: 1, - ..Default::default() - }, - ..Default::default() - }; - - unsafe { device.cmd_pipeline_barrier( - texture_command_buffer, - vk::PipelineStageFlags::BOTTOM_OF_PIPE, - vk::PipelineStageFlags::TRANSFER, - vk::DependencyFlags::empty(), - &[], - &[], - &[barrier], - ) }; - - let buffer_copy_regions = vk::BufferImageCopy::builder() - .image_subresource( - vk::ImageSubresourceLayers::builder() - .aspect_mask(vk::ImageAspectFlags::COLOR) - .layer_count(1) - .build() - ) - .image_extent(image_extent) - .build(); - - unsafe { device.cmd_copy_buffer_to_image( - texture_command_buffer, - image_buffer.buffer, - image, - vk::ImageLayout::TRANSFER_DST_OPTIMAL, - &[buffer_copy_regions], - ) }; - - let barrier_end = vk::ImageMemoryBarrier { - src_access_mask: vk::AccessFlags::TRANSFER_WRITE, - dst_access_mask: vk::AccessFlags::SHADER_READ, - old_layout: vk::ImageLayout::TRANSFER_DST_OPTIMAL, - new_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL, - image, - subresource_range: vk::ImageSubresourceRange { - aspect_mask: vk::ImageAspectFlags::COLOR, - level_count: 1, - layer_count: 1, - ..Default::default() - }, - ..Default::default() - }; - - unsafe { device.cmd_pipeline_barrier( - texture_command_buffer, - vk::PipelineStageFlags::TRANSFER, - vk::PipelineStageFlags::FRAGMENT_SHADER, - vk::DependencyFlags::empty(), - &[], - &[], - &[barrier_end], - ) }; - - }, - ); - - Self { - graphics: graphics.clone(), - image, - memory, - buffer: Some(image_buffer), - view: None, - sampler: None, - } - } - - pub fn new_from_dmabuf(graphics: Arc, frame: &DmabufFrame) -> Self { - debug_assert!(frame.num_planes == 1); - let plane = &frame.planes[0]; - debug_assert!(plane.fd.is_some()); - - let format = match frame.format.fourcc { - DRM_FORMAT_ABGR8888 => vk::Format::R8G8B8A8_UNORM, - DRM_FORMAT_XBGR8888 => vk::Format::R8G8B8A8_UNORM, - DRM_FORMAT_ARGB8888 => vk::Format::B8G8R8A8_UNORM, - DRM_FORMAT_XRGB8888 => vk::Format::B8G8R8A8_UNORM, - _ => panic!("Unsupported dmabuf format {:x}", frame.format.fourcc), - }; - - let image = { - let layout = vk::SubresourceLayout::builder() - .offset(plane.offset as _) - .row_pitch(plane.stride as _) - .size(0) - .array_pitch(0) - .depth_pitch(0) - .build(); - - let mut drm_info = vk::ImageDrmFormatModifierExplicitCreateInfoEXT::builder() - .drm_format_modifier(frame.format.modifier) - .plane_layouts(slice::from_ref(&layout)); - - let mut mem_info = vk::ExternalMemoryImageCreateInfo::builder() - .handle_types(vk::ExternalMemoryHandleTypeFlags::DMA_BUF_EXT); - - let image_create_info = vk::ImageCreateInfo::builder() - .image_type(vk::ImageType::TYPE_2D) - .format(format) - .extent(vk::Extent3D { - width: frame.format.width, - height: frame.format.height, - depth: 1, - }) - .mip_levels(1) - .array_layers(1) - .samples(vk::SampleCountFlags::TYPE_1) - .tiling(vk::ImageTiling::DRM_FORMAT_MODIFIER_EXT) - .usage(vk::ImageUsageFlags::TRANSFER_SRC | vk::ImageUsageFlags::SAMPLED) - .sharing_mode(vk::SharingMode::EXCLUSIVE) - .push_next(&mut drm_info) - .push_next(&mut mem_info) - .build(); - - unsafe { graphics.device.create_image(&image_create_info, None).unwrap() } - }; - - let memory_requirements = unsafe { graphics.device.get_image_memory_requirements(image) }; - let memory_type_index = find_memorytype_index( - &memory_requirements, - &graphics.device_memory_properties, - vk::MemoryPropertyFlags::DEVICE_LOCAL, - ).unwrap(); - - let memory = { - let mut fd_info = vk::ImportMemoryFdInfoKHR::builder() - .handle_type(vk::ExternalMemoryHandleTypeFlags::DMA_BUF_EXT) - .fd(plane.fd.unwrap()) - .build(); - - let mut ded_req = vk::MemoryDedicatedAllocateInfo::builder() - .image(image) - .build(); - - let alloc_info = vk::MemoryAllocateInfo::builder() - .allocation_size(memory_requirements.size) - .memory_type_index(memory_type_index) - .push_next(&mut fd_info) - .push_next(&mut ded_req) - .build(); - - unsafe { graphics.device.allocate_memory(&alloc_info, None).unwrap() } - }; - - unsafe { graphics.device.bind_image_memory(image, memory, 0).unwrap() }; - - Self { - graphics: graphics.clone(), - image, - memory, - buffer: None, - view: None, - sampler: None, - } - } -} - -impl Drop for VkImage { - fn drop(&mut self) { - unsafe { - if let Some(buffer) = self.buffer.as_ref() { - self.graphics.device.free_memory(buffer.memory, None); - self.graphics.device.destroy_buffer(buffer.buffer, None); - } - if let Some(view) = self.view { - self.graphics.device.destroy_image_view(view, None); - } - self.graphics.device.free_memory(self.memory, None); - self.graphics.device.destroy_image(self.image, None); - } - } -} - -const ENTRY_POINT_MAIN: &'static CStr = cstr!("main"); -pub struct VkShader { - pub graphics: Arc, - pub module: vk::ShaderModule, - pub descriptor_types: Option>, -} - -impl VkShader { - fn new(graphics: Arc, bytes: &[u8], descriptor_types: Option>) -> Arc { - let mut spv = ash::util::read_spv(&mut Cursor::new(bytes)).unwrap(); - let module_create_info = vk::ShaderModuleCreateInfo::builder().code(&mut spv); - let module = unsafe { graphics.device.create_shader_module(&module_create_info, None).unwrap() }; - - Arc::new(Self { - graphics, - module, - descriptor_types, - }) - } -} - -impl Drop for VkShader { - fn drop(&mut self) { - unsafe { - self.graphics.device.destroy_shader_module(self.module, None); - } - } -} - -pub struct VkPipeline { - pub graphics: Arc, - pub pipeline: vk::Pipeline, - pub pipeline_layout: vk::PipelineLayout, - pub desc_set_layouts: Vec, - pub descriptor_pool: vk::DescriptorPool, - pub descriptor_sets: Vec, - pub index_buffer: Arc, - pub vertex_buffer: Arc, -} - -impl VkPipeline { - pub fn new(graphics: Arc, vert: Arc, frag: Arc, format: vk::Format) -> Self { - let shader_stage_create_infos = [ - vk::PipelineShaderStageCreateInfo { - module: vert.module, - p_name: ENTRY_POINT_MAIN.as_ptr(), - stage: vk::ShaderStageFlags::VERTEX, - ..Default::default() - }, - vk::PipelineShaderStageCreateInfo { - module: frag.module, - p_name: ENTRY_POINT_MAIN.as_ptr(), - stage: vk::ShaderStageFlags::FRAGMENT, - ..Default::default() - }, - ]; - - let vertex_input_binding_descriptions = [vk::VertexInputBindingDescription { - binding: 0, - stride: mem::size_of::() as u32, - input_rate: vk::VertexInputRate::VERTEX, - }]; - - let vertex_input_attribute_descriptions = [ - vk::VertexInputAttributeDescription { - location: 0, - binding: 0, - format: vk::Format::R32G32_SFLOAT, - offset: offset_of!(Vertex, in_pos) as u32, - }, - vk::VertexInputAttributeDescription { - location: 1, - binding: 0, - format: vk::Format::R32G32_SFLOAT, - offset: offset_of!(Vertex, in_uv) as u32, - }, - ]; - - let vertex_input_state_info = vk::PipelineVertexInputStateCreateInfo::builder() - .vertex_attribute_descriptions(&vertex_input_attribute_descriptions) - .vertex_binding_descriptions(&vertex_input_binding_descriptions) - .build(); - - let vertex_input_assembly_state_info = vk::PipelineInputAssemblyStateCreateInfo::builder() - .topology(vk::PrimitiveTopology::TRIANGLE_LIST) - .build(); - - let desc_layout_bindings = frag.descriptor_types.iter().flatten().enumerate().map(|(i, &desc_type)| { - vk::DescriptorSetLayoutBinding { - binding: i as u32, - descriptor_type: desc_type, - descriptor_count: 1, - stage_flags: vk::ShaderStageFlags::FRAGMENT, - ..Default::default() - } - }).collect::>(); - - let descriptor_info = - vk::DescriptorSetLayoutCreateInfo::builder() - .bindings(&desc_layout_bindings); - - let desc_set_layouts = unsafe { - vec![graphics - .device - .create_descriptor_set_layout(&descriptor_info, None) - .unwrap()] - }; - - let layout_create_info = - vk::PipelineLayoutCreateInfo::builder().set_layouts(&desc_set_layouts); - - let pipeline_layout = unsafe { - graphics - .device - .create_pipeline_layout(&layout_create_info, None) - .unwrap() - }; - - let viewport = vk::Viewport::builder().width(1.0).height(1.0).max_depth(1.0).build(); - let scissor = vk::Rect2D::builder().extent(vk::Extent2D { width: 1, height: 1 }).build(); - - let viewport_state_info = vk::PipelineViewportStateCreateInfo::builder() - .scissors(slice::from_ref(&scissor)) - .viewports(slice::from_ref(&viewport)) - .build(); - - let rasterization_info = vk::PipelineRasterizationStateCreateInfo::builder() - .front_face(vk::FrontFace::COUNTER_CLOCKWISE) - .line_width(1.0) - .polygon_mode(vk::PolygonMode::FILL) - .build(); - - let multisample_state_info = vk::PipelineMultisampleStateCreateInfo::builder() - .rasterization_samples(vk::SampleCountFlags::TYPE_1) - .build(); - - let color_blend_attachment_states = [vk::PipelineColorBlendAttachmentState { - blend_enable: 1, - src_color_blend_factor: vk::BlendFactor::SRC_COLOR, - dst_color_blend_factor: vk::BlendFactor::ONE_MINUS_DST_COLOR, - color_blend_op: vk::BlendOp::ADD, - src_alpha_blend_factor: vk::BlendFactor::ZERO, - dst_alpha_blend_factor: vk::BlendFactor::ZERO, - alpha_blend_op: vk::BlendOp::ADD, - color_write_mask: vk::ColorComponentFlags::RGBA, - }]; - - let color_blend_state = vk::PipelineColorBlendStateCreateInfo::builder() - .logic_op(vk::LogicOp::CLEAR) - .attachments(&color_blend_attachment_states) - .build(); - - let dynamic_state = [vk::DynamicState::VIEWPORT, vk::DynamicState::SCISSOR]; - let dynamic_state_info = - vk::PipelineDynamicStateCreateInfo::builder() - .dynamic_states(&dynamic_state) - .build(); - - let mut pipeline_rendering_create_info = vk::PipelineRenderingCreateInfo::builder() - .color_attachment_formats(slice::from_ref(&format)); - - let info = vk::GraphicsPipelineCreateInfo::builder() - .stages(&shader_stage_create_infos) - .vertex_input_state(&vertex_input_state_info) - .input_assembly_state(&vertex_input_assembly_state_info) - .viewport_state(&viewport_state_info) - .rasterization_state(&rasterization_info) - .multisample_state(&multisample_state_info) - .color_blend_state(&color_blend_state) - .dynamic_state(&dynamic_state_info) - .layout(pipeline_layout) - .push_next(&mut pipeline_rendering_create_info) - .build(); - - let pipeline = unsafe { graphics.device.create_graphics_pipelines(vk::PipelineCache::null(), slice::from_ref(&info), None).unwrap()[0] }; - - let descriptor_sizes = frag.descriptor_types.iter().flatten().map(|&desc_type| { - vk::DescriptorPoolSize { - ty: desc_type, - descriptor_count: 1, - } - }).collect::>(); - - let descriptor_pool_info = vk::DescriptorPoolCreateInfo::builder() - .pool_sizes(&descriptor_sizes) - .max_sets(1) - .build(); - - let descriptor_pool = unsafe { graphics.device.create_descriptor_pool(&descriptor_pool_info, None).unwrap() }; - - let desc_alloc_info = vk::DescriptorSetAllocateInfo::builder() - .descriptor_pool(descriptor_pool) - .set_layouts(&desc_set_layouts) - .build(); - - let descriptor_sets = unsafe { graphics.device.allocate_descriptor_sets(&desc_alloc_info).unwrap() }; - - let index_buffer = graphics.create_buffer(vk::BufferUsageFlags::INDEX_BUFFER, &INDICES); - let vertex_buffer = graphics.create_buffer(vk::BufferUsageFlags::VERTEX_BUFFER, &VERTICES); - - Self { - graphics, - pipeline, - pipeline_layout, - descriptor_pool, - desc_set_layouts, - descriptor_sets, - index_buffer, - vertex_buffer, - } - } - - pub fn render(&self, frame: &VkFrame, rect: vk::Rect2D) { - unsafe { - self.graphics.device.cmd_bind_pipeline(frame.command_buffer, vk::PipelineBindPoint::GRAPHICS, self.pipeline); - - let viewport = vk::Viewport::builder().width(rect.extent.width as _).height(rect.extent.height as _).max_depth(1.0).build(); - - self.graphics.device.cmd_set_viewport(frame.command_buffer, 0, slice::from_ref(&viewport)); - self.graphics.device.cmd_set_scissor(frame.command_buffer, 0, slice::from_ref(&rect)); - - self.graphics.device.cmd_bind_vertex_buffers(frame.command_buffer, 0, slice::from_ref(&self.vertex_buffer.buffer), &[0]); - self.graphics.device.cmd_bind_index_buffer(frame.command_buffer, self.index_buffer.buffer, 0, vk::IndexType::UINT16); - - self.graphics.device.cmd_draw_indexed(frame.command_buffer, 6, 1, 0, 0, 1); - } - } - - pub fn bind_descriptors(&self, descriptors: &[VkDescriptor]) { - let descriptor_write = descriptors.iter().enumerate().map(|(i, desciptor)| { - match desciptor { - VkDescriptor::Image(image) => { - let descriptor_image_info = vk::DescriptorImageInfo { - sampler: vk::Sampler::null(), - image_view: image.view.unwrap(), - image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL, - }; - vk::WriteDescriptorSet::builder() - .dst_set(self.descriptor_sets[0]) - .dst_binding(i as u32) - .descriptor_type(vk::DescriptorType::SAMPLED_IMAGE) - .image_info(&[descriptor_image_info]) - .build() - }, - VkDescriptor::Buffer(buffer) => { - let descriptor_buffer_info = vk::DescriptorBufferInfo { - buffer: buffer.buffer, - offset: 0, - range: vk::WHOLE_SIZE, - }; - vk::WriteDescriptorSet::builder() - .dst_set(self.descriptor_sets[0]) - .dst_binding(i as u32) - .descriptor_type(vk::DescriptorType::UNIFORM_BUFFER) - .buffer_info(&[descriptor_buffer_info]) - .build() - }, - } - }).collect::>(); - println!("x"); - unsafe { self.graphics.device.update_descriptor_sets(&descriptor_write, &[]) }; - println!("y"); - } -} - -impl Drop for VkPipeline { - fn drop(&mut self) { - unsafe { - self.graphics.device.destroy_pipeline(self.pipeline, None); - self.graphics.device.destroy_pipeline_layout(self.pipeline_layout, None); - self.graphics.device.destroy_descriptor_pool(self.descriptor_pool, None); - for &desc_set_layout in self.desc_set_layouts.iter() { - self.graphics.device.destroy_descriptor_set_layout(desc_set_layout, None); - } - } - } -} - -pub enum VkDescriptor { - Image(Arc), - Buffer(Arc), -} - -pub fn find_memorytype_index( - memory_req: &vk::MemoryRequirements, - memory_prop: &vk::PhysicalDeviceMemoryProperties, - flags: vk::MemoryPropertyFlags, -) -> Option { - memory_prop.memory_types[..memory_prop.memory_type_count as _] - .iter() - .enumerate() - .find(|(index, memory_type)| { - (1 << index) & memory_req.memory_type_bits != 0 - && memory_type.property_flags & flags == flags - }) - .map(|(index, _memory_type)| index as _) -} - -/// Helper function for submitting command buffers. Immediately waits for the fence before the command buffer -/// is executed. That way we can delay the waiting for the fences by 1 frame which is good for performance. -/// Make sure to create the fence in a signaled state on the first use. -#[allow(clippy::too_many_arguments)] -pub fn record_submit_commandbuffer( - device: &ash::Device, - command_buffer: vk::CommandBuffer, - command_buffer_reuse_fence: vk::Fence, - submit_queue: vk::Queue, - wait_mask: &[vk::PipelineStageFlags], - wait_semaphores: &[vk::Semaphore], - signal_semaphores: &[vk::Semaphore], - f: F, -) { - unsafe { - device - .wait_for_fences(&[command_buffer_reuse_fence], true, std::u64::MAX) - .expect("Wait for fence failed."); - - device - .reset_fences(&[command_buffer_reuse_fence]) - .expect("Reset fences failed."); - - device - .reset_command_buffer( - command_buffer, - vk::CommandBufferResetFlags::RELEASE_RESOURCES, - ) - .expect("Reset command buffer failed."); - - let command_buffer_begin_info = vk::CommandBufferBeginInfo::builder() - .flags(vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT); - - device - .begin_command_buffer(command_buffer, &command_buffer_begin_info) - .expect("Begin commandbuffer"); - f(device, command_buffer); - device - .end_command_buffer(command_buffer) - .expect("End commandbuffer"); - - let command_buffers = vec![command_buffer]; - - let submit_info = vk::SubmitInfo::builder() - .wait_semaphores(wait_semaphores) - .wait_dst_stage_mask(wait_mask) - .command_buffers(&command_buffers) - .signal_semaphores(signal_semaphores); - - device - .queue_submit( - submit_queue, - &[submit_info.build()], - command_buffer_reuse_fence, - ) - .expect("queue submit failed."); - } -} - -unsafe extern "system" fn vulkan_debug_callback( - message_severity: vk::DebugUtilsMessageSeverityFlagsEXT, - message_type: vk::DebugUtilsMessageTypeFlagsEXT, - p_callback_data: *const vk::DebugUtilsMessengerCallbackDataEXT, - _user_data: *mut std::os::raw::c_void, -) -> vk::Bool32 { - let callback_data = *p_callback_data; - let message_id_number = callback_data.message_id_number; - - let message_id_name = if callback_data.p_message_id_name.is_null() { - Cow::from("") - } else { - CStr::from_ptr(callback_data.p_message_id_name).to_string_lossy() - }; - - let message = if callback_data.p_message.is_null() { - Cow::from("") - } else { - CStr::from_ptr(callback_data.p_message).to_string_lossy() - }; - - println!( - "{message_severity:?}:\n{message_type:?} [{message_id_name} ({message_id_number})] : {message}\n", - ); - - vk::FALSE -} diff --git a/src/gui/font.rs b/src/gui/font.rs index 15b48d7..8ae11d6 100644 --- a/src/gui/font.rs +++ b/src/gui/font.rs @@ -3,7 +3,6 @@ use std::{rc::Rc, str::FromStr, sync::Arc}; use fontconfig::{FontConfig, OwnedPattern}; use freetype::{bitmap::PixelMode, face::LoadFlag, Face, Library}; use idmap::IdMap; -use log::debug; use vulkano::{command_buffer::CommandBufferUsage, format::Format, image::ImmutableImage}; use crate::graphics::WlxGraphics; @@ -116,7 +115,7 @@ impl FontCache { let pattern = pattern.font_match(&mut self.fc); if let Some(path) = pattern.filename() { - debug!( + log::debug!( "Loading font: {} {}pt", pattern.name().unwrap_or(path), size @@ -203,7 +202,7 @@ impl FontCache { let mut cmd_buffer = graphics.create_command_buffer(CommandBufferUsage::OneTimeSubmit); let texture = cmd_buffer.texture2d(bmp.width() as _, bmp.rows() as _, format, buf); - let _ = cmd_buffer.end_and_execute(); + cmd_buffer.build_and_execute_now(); let g = Glyph { tex: Some(texture), diff --git a/src/gui/mod.rs b/src/gui/mod.rs index 6e5212e..82d96dd 100644 --- a/src/gui/mod.rs +++ b/src/gui/mod.rs @@ -93,6 +93,7 @@ impl CanvasBuilder { } // Creates a label with fg_color, font_size inherited from the canvas + #[allow(dead_code)] pub fn label_centered( &mut self, x: f32, @@ -320,13 +321,13 @@ impl Canvas { .canvas .graphics .create_command_buffer(CommandBufferUsage::OneTimeSubmit) - .begin(self.view_bg.clone(), None); + .begin(self.view_bg.clone()); for c in self.controls.iter_mut() { if let Some(fun) = c.on_render_bg { fun(c, &self.canvas, app, &mut cmd_buffer); } } - let _ = cmd_buffer.end_render_and_execute(); + cmd_buffer.end_render().build_and_execute_now() } fn render_fg(&mut self, app: &mut AppState) { @@ -334,17 +335,13 @@ impl Canvas { .canvas .graphics .create_command_buffer(CommandBufferUsage::OneTimeSubmit) - .begin(self.view_fg.clone(), None); + .begin(self.view_fg.clone()); for c in self.controls.iter_mut() { if let Some(fun) = c.on_render_fg { fun(c, &self.canvas, app, &mut cmd_buffer); } } - let _ = cmd_buffer.end_render_and_execute(); - } - - pub fn render_view(&self) -> Arc> { - self.view_final.clone() + cmd_buffer.end_render().build_and_execute_now() } } @@ -385,7 +382,6 @@ impl InteractionHandler for Canvas { impl OverlayRenderer for Canvas { fn init(&mut self, app: &mut AppState) { self.render_bg(app); - self.render_fg(app); } fn pause(&mut self, _app: &mut AppState) {} @@ -423,10 +419,7 @@ impl OverlayRenderer for Canvas { .canvas .graphics .create_command_buffer(CommandBufferUsage::OneTimeSubmit) - .begin( - self.view_final.clone(), - Some(ImageLayout::TransferSrcOptimal), - ); + .begin(self.view_final.clone()); if dirty { self.render_fg(app); @@ -451,7 +444,7 @@ impl OverlayRenderer for Canvas { // mostly static text cmd_buffer.run_ref(&self.pass_fg); { - let _ = cmd_buffer.end_render_and_execute(); + let _ = cmd_buffer.end_render().build_and_execute(); } self.canvas .graphics @@ -478,7 +471,6 @@ pub struct Control { text: Arc, size: isize, dirty: bool, - pass_hl: Option<(WlxPass, WlxPass)>, pub on_update: Option, pub on_press: Option, @@ -524,7 +516,6 @@ impl Control { test_highlight: None, on_press: None, on_release: None, - pass_hl: None, } } @@ -537,11 +528,6 @@ impl Control { self.dirty = true; } - #[inline(always)] - pub fn get_text(&self) -> &str { - &self.text - } - fn render_rect( &self, canvas: &CanvasData, diff --git a/src/input.rs b/src/input.rs index 569a4a2..807ded2 100644 --- a/src/input.rs +++ b/src/input.rs @@ -6,7 +6,6 @@ use input_linux::{ UInputHandle, }; use libc::{input_event, timeval}; -use log::{error, info}; use once_cell::sync::Lazy; use std::fs::File; use std::mem::transmute; @@ -14,11 +13,11 @@ use strum::{EnumIter, EnumString, IntoEnumIterator}; pub fn initialize_input() -> Box { if let Some(uinput) = UInputProvider::try_new() { - info!("Initialized uinput."); + log::info!("Initialized uinput."); return Box::new(uinput); } - error!("Could not create uinput provider. Keyboard/Mouse input will not work!"); - error!("Check if you're in `input` group: `id -nG`"); + log::error!("Could not create uinput provider. Keyboard/Mouse input will not work!"); + log::error!("Check if you're in `input` group: `id -nG`"); Box::new(DummyProvider {}) } @@ -64,7 +63,7 @@ impl UInputProvider { version: 5, }; - let name = b"WlxOverlay Keyboard-Mouse Hybrid Thing\0"; + let name = b"WlxOverlay-S Keyboard-Mouse Hybrid Thing\0"; let abs_info = vec![ AbsoluteInfoSetup { @@ -145,6 +144,8 @@ impl InputProvider for UInputProvider { } self.mouse_moved = true; + log::info!("Mouse move: {:?}", pos); + let pos = pos * (MOUSE_EXTENT / self.desktop_extent); let time = get_time(); @@ -154,7 +155,7 @@ impl InputProvider for UInputProvider { new_event(time, EV_SYN, 0, 0), ]; if let Err(res) = self.handle.write(&events) { - error!("{}", res.to_string()); + log::error!("{}", res.to_string()); } } fn send_button(&self, button: u16, down: bool) { @@ -164,7 +165,7 @@ impl InputProvider for UInputProvider { new_event(time, EV_SYN, 0, 0), ]; if let Err(res) = self.handle.write(&events) { - error!("{}", res.to_string()); + log::error!("send_button: {}", res.to_string()); } } fn wheel(&self, delta: i32) { @@ -174,7 +175,7 @@ impl InputProvider for UInputProvider { new_event(time, EV_SYN, 0, 0), ]; if let Err(res) = self.handle.write(&events) { - error!("{}", res.to_string()); + log::error!("wheel: {}", res.to_string()); } } fn set_modifiers(&mut self, modifiers: u8) { @@ -195,11 +196,11 @@ impl InputProvider for UInputProvider { new_event(time, EV_SYN, 0, 0), ]; if let Err(res) = self.handle.write(&events) { - error!("{}", res.to_string()); + log::error!("send_key: {}", res.to_string()); } } fn set_desktop_extent(&mut self, extent: Vec2) { - info!("Desktop extent: {:?}", extent); + log::info!("Desktop extent: {:?}", extent); self.desktop_extent = extent; } fn on_new_frame(&mut self) { diff --git a/src/main.rs b/src/main.rs index 1ec3ec5..507ee38 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,11 +9,10 @@ mod state; use crate::backend::openvr::openvr_run; use env_logger::Env; -use log::info; fn main() { env_logger::Builder::from_env(Env::default().default_filter_or("info")).init(); - info!( + log::info!( "Welcome to {} version {}!", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION") diff --git a/src/main.rs.bak2 b/src/main.rs.bak2 deleted file mode 100644 index 8630400..0000000 --- a/src/main.rs.bak2 +++ /dev/null @@ -1,159 +0,0 @@ -#[allow(dead_code)] -#[allow(unused_imports)] - -mod graphics; -//mod gui; -//mod interactions; -//mod overlay; -//mod state; - -use core::slice; - -use ash::vk; -use env_logger::Env; -use glam::f32::Vec4; -use log::{info, warn}; -use wlx_capture::{wlr::WlrDmabufCapture, wayland::WlxClient, WlxCapture, frame::WlxFrame}; - -use crate::{graphics::{VkGraphics, VkDescriptor}}; - -fn main() { - env_logger::Builder::from_env(Env::default().default_filter_or("info")).init(); - info!("Welcome to {} version {}!", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")); - -// let mut app = AppState { -// fc: gui::font::FontCache::new(), -// session: state::AppSession::load(), -// }; - - let wl = WlxClient::new().unwrap(); - let output_id = wl.outputs[0].id; - let mut capture = WlrDmabufCapture::new(wl, output_id).unwrap(); - let rx = capture.init(); - - let gfx = VkGraphics::new(); - let vert = gfx.create_shader(include_bytes!("shaders/vert-common.spv"), None); - let frag_sprite = gfx.create_shader( - include_bytes!("shaders/frag-sprite.spv"), - Some(vec![vk::DescriptorType::COMBINED_IMAGE_SAMPLER]) - ); - let frag_srgb = gfx.create_shader( - include_bytes!("shaders/frag-srgb.spv"), - Some(vec![vk::DescriptorType::COMBINED_IMAGE_SAMPLER]) - ); - let frag_glyph = gfx.create_shader( - include_bytes!("shaders/frag-glyph.spv"), - Some(vec![vk::DescriptorType::COMBINED_IMAGE_SAMPLER, vk::DescriptorType::UNIFORM_BUFFER]) - ); - let frag_color = gfx.create_shader( - include_bytes!("shaders/frag-color.spv"), - Some(vec![vk::DescriptorType::UNIFORM_BUFFER]) - ); - - let pipeline = gfx.create_pipeline(vert, frag_color, gfx.swapchain_format); - - let color_buf = gfx.create_buffer(vk::BufferUsageFlags::UNIFORM_BUFFER, &[Vec4::new(1.0, 0.0, 1.0, 1.0); 16]); - - gfx.render_loop(|| { - let frame = gfx.create_frame(); - - unsafe { gfx.device.reset_command_pool(frame.command_pool, vk::CommandPoolResetFlags::RELEASE_RESOURCES) }.unwrap(); - - let (present_index, _) = unsafe { - gfx.swapchain_loader.acquire_next_image( - gfx.swapchain, - std::u64::MAX, - frame.present_semaphore, - vk::Fence::null() - ).unwrap() - }; - - let command_buffer_begin_info = vk::CommandBufferBeginInfo::builder() - .flags(vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT) - .build(); - - unsafe { gfx.device.begin_command_buffer(frame.command_buffer, &command_buffer_begin_info) }.unwrap(); - - let image = gfx.present_images[present_index as usize]; - - let image_memory_barrier = vk::ImageMemoryBarrier2::builder() - .src_stage_mask(vk::PipelineStageFlags2::TOP_OF_PIPE) - .dst_stage_mask(vk::PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT) - .dst_access_mask(vk::AccessFlags2::COLOR_ATTACHMENT_WRITE) - .old_layout(vk::ImageLayout::UNDEFINED) - .new_layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL) - .image(image) - .subresource_range(vk::ImageSubresourceRange::builder().aspect_mask(vk::ImageAspectFlags::COLOR).level_count(1).layer_count(1).build()) - .build(); - - unsafe { gfx.device.cmd_pipeline_barrier2(frame.command_buffer, &vk::DependencyInfo::builder().image_memory_barriers(slice::from_ref(&image_memory_barrier)).build()) }; - - let color_attachment = vk::RenderingAttachmentInfo::builder() - .image_view(gfx.present_image_views[present_index as usize]) - .image_layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL) - .load_op(vk::AttachmentLoadOp::CLEAR) - .store_op(vk::AttachmentStoreOp::STORE) - .clear_value(vk::ClearValue { - color: vk::ClearColorValue { - float32: [0.0, 0.0, 0.0, 1.0] - } - }); - - let rendering_info = vk::RenderingInfo::builder() - .render_area(vk::Rect2D::builder().extent(vk::Extent2D::builder().width(1600).height(900).build()).build()) - .layer_count(1) - .color_attachments(slice::from_ref(&color_attachment)) - .build(); - - - unsafe { gfx.device.cmd_begin_rendering(frame.command_buffer, &rendering_info) }; - - let descriptor = VkDescriptor::Buffer(color_buf.clone()); - pipeline.bind_descriptors(slice::from_ref(&descriptor)); - pipeline.render(&frame, vk::Rect2D { - offset: vk::Offset2D { x: 0, y: 0 }, - extent: vk::Extent2D { width: 1600, height: 900 } - }); - - unsafe { gfx.device.cmd_end_rendering(frame.command_buffer) }; - - - let image_memory_barrier = vk::ImageMemoryBarrier2::builder() - .src_stage_mask(vk::PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT) - .src_access_mask(vk::AccessFlags2::COLOR_ATTACHMENT_WRITE) - .dst_stage_mask(vk::PipelineStageFlags2::BOTTOM_OF_PIPE) - .old_layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL) - .new_layout(vk::ImageLayout::PRESENT_SRC_KHR) - .image(image) - .subresource_range(vk::ImageSubresourceRange::builder().aspect_mask(vk::ImageAspectFlags::COLOR).level_count(1).layer_count(1).build()) - .build(); - - unsafe { - gfx.device.cmd_pipeline_barrier2(frame.command_buffer, &vk::DependencyInfo::builder().image_memory_barriers(slice::from_ref(&image_memory_barrier)).build()); - }; - - unsafe { gfx.device.end_command_buffer(frame.command_buffer) }.unwrap(); - - let wait_semaphores = [frame.present_semaphore]; - let wait_dst_stage_mask = [vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT]; - - let submit_info = vk::SubmitInfo::builder() - .wait_semaphores(&wait_semaphores) - .wait_dst_stage_mask(&wait_dst_stage_mask) - .command_buffers(slice::from_ref(&frame.command_buffer)) - .signal_semaphores(slice::from_ref(&frame.render_semaphore)); - - unsafe { gfx.device.queue_submit(gfx.present_queue, slice::from_ref(&submit_info), frame.fence) }.unwrap(); - - let present_info = vk::PresentInfoKHR::builder() - .wait_semaphores(slice::from_ref(&frame.present_semaphore)) - .swapchains(slice::from_ref(&gfx.swapchain)) - .image_indices(slice::from_ref(&present_index)) - .build(); - - unsafe { gfx.swapchain_loader.queue_present(gfx.present_queue, &present_info).unwrap() }; - }); - - unsafe { gfx.device.device_wait_idle().unwrap() }; -} - diff --git a/src/overlays/keyboard.rs b/src/overlays/keyboard.rs index b7e0ce1..c4ec0cc 100644 --- a/src/overlays/keyboard.rs +++ b/src/overlays/keyboard.rs @@ -16,7 +16,6 @@ use crate::{ state::AppState, }; use glam::{vec2, vec3a}; -use log::error; use once_cell::sync::Lazy; use regex::Regex; use rodio::{Decoder, OutputStream, Source}; @@ -88,7 +87,7 @@ where args: exec_args.iter().skip(1).cloned().collect(), }); } else { - error!("Unknown key: {}", key); + log::error!("Unknown key: {}", key); } if let Some(state) = maybe_state { @@ -109,7 +108,7 @@ where OverlayData { state: OverlayState { - name: Arc::from("Kbd"), + name: Arc::from("kbd"), show_hide: true, width: LAYOUT.row_size * 0.05, size: (size.x as _, size.y as _), @@ -217,7 +216,7 @@ impl KeyboardData { let _ = handle.play_raw(source.convert_samples()); self.audio_stream = Some(stream); } else { - error!("Failed to play key click"); + log::error!("Failed to play key click"); } } } @@ -339,7 +338,7 @@ fn key_events_for_macro(macro_verbs: &Vec) -> Vec<(VirtualKey, bool)> { } else if state.as_str() == "DOWN" { key_events.push((virtual_key, true)); } else { - error!( + log::error!( "Unknown key state in macro: {}, looking for UP or DOWN.", state.as_str() ); @@ -350,7 +349,7 @@ fn key_events_for_macro(macro_verbs: &Vec) -> Vec<(VirtualKey, bool)> { key_events.push((virtual_key, false)); } } else { - error!("Unknown virtual key: {}", &caps[1]); + log::error!("Unknown virtual key: {}", &caps[1]); return vec![]; } } diff --git a/src/overlays/screen.rs b/src/overlays/screen.rs index 0ab2e54..87e9e68 100644 --- a/src/overlays/screen.rs +++ b/src/overlays/screen.rs @@ -1,4 +1,3 @@ -use log::{info, warn}; use std::{ f32::consts::PI, path::Path, @@ -6,9 +5,14 @@ use std::{ time::{Duration, Instant}, }; use vulkano::{ + buffer::Subbuffer, command_buffer::CommandBufferUsage, format::Format, - image::{view::ImageView, ImageAccess, ImageLayout, ImageViewAbstract, ImmutableImage}, + image::{ + view::ImageView, AttachmentImage, ImageAccess, ImageLayout, ImageViewAbstract, StorageImage, + }, + sampler::Filter, + sync::GpuFuture, Handle, VulkanObject, }; use wlx_capture::{ @@ -26,7 +30,9 @@ use crate::{ input::{InteractionHandler, PointerHit, PointerMode}, overlay::{OverlayData, OverlayRenderer, OverlayState, SplitOverlayBackend}, }, + graphics::{Vert2Uv, WlxGraphics, WlxPipeline}, input::{MOUSE_LEFT, MOUSE_MIDDLE, MOUSE_RIGHT}, + shaders::{frag_sprite, vert_common}, state::{AppSession, AppState}, }; @@ -66,6 +72,7 @@ impl ScreenInteractionHandler { impl InteractionHandler for ScreenInteractionHandler { fn on_hover(&mut self, app: &mut AppState, hit: &PointerHit) { + log::info!("Hover: {:?}", hit.uv); if self.next_move < Instant::now() { let pos = self.mouse_transform.transform_point2(hit.uv); app.input.mouse_move(pos); @@ -82,7 +89,8 @@ impl InteractionHandler for ScreenInteractionHandler { }; if pressed { - self.next_move = Instant::now() + Duration::from_millis(300); + self.next_move = + Instant::now() + Duration::from_millis(app.session.click_freeze_time_ms); } app.input.send_button(btn, pressed); @@ -97,11 +105,106 @@ impl InteractionHandler for ScreenInteractionHandler { fn on_left(&mut self, _app: &mut AppState, _hand: usize) {} } +struct ScreenPipeline { + graphics: Arc, + pipeline: Arc, + vertex_buffer: Subbuffer<[Vert2Uv]>, + target_layout: ImageLayout, + pub view: Arc>, +} + +impl ScreenPipeline { + fn new(graphics: Arc, image: &StorageImage) -> Self { + let pipeline = graphics.create_pipeline( + vert_common::load(graphics.device.clone()).unwrap(), + frag_sprite::load(graphics.device.clone()).unwrap(), + Format::R8G8B8A8_UNORM, + ); + + let dim = image.dimensions().width_height(); + + let vertex_buffer = + graphics.upload_verts(dim[0] as _, dim[1] as _, 0.0, 0.0, dim[0] as _, dim[1] as _); + + let render_texture = graphics.render_texture(dim[0], dim[1], Format::R8G8B8A8_UNORM); + + let view = ImageView::new_default(render_texture).unwrap(); + + Self { + graphics, + pipeline, + vertex_buffer, + view, + target_layout: ImageLayout::Undefined, + } + } + + fn render(&mut self, image: Arc) { + if image.inner().image.handle().as_raw() + == self.view.image().inner().image.handle().as_raw() + { + return; + } + + let mut command_buffer = self + .graphics + .create_command_buffer(CommandBufferUsage::OneTimeSubmit) + .begin(self.view.clone()); + + let set0 = self.pipeline.uniform_sampler( + 0, + ImageView::new_default(image).unwrap(), + Filter::Linear, + ); + + let dim = self.view.dimensions().width_height(); + let dim = [dim[0] as f32, dim[1] as f32]; + + let pass = self.pipeline.create_pass( + dim, + self.vertex_buffer.clone(), + self.graphics.quad_indices.clone(), + vec![set0], + ); + command_buffer.run_ref(&pass); + + let image = self.view.image().inner().image.clone(); + + if self.target_layout == ImageLayout::TransferSrcOptimal { + self.graphics + .transition_layout( + image.clone(), + ImageLayout::TransferSrcOptimal, + ImageLayout::ColorAttachmentOptimal, + ) + .wait(None) + .unwrap(); + } + + { + let mut exec = command_buffer.end_render().build_and_execute(); + exec.flush().unwrap(); + exec.cleanup_finished(); + } + + self.graphics + .transition_layout( + image, + ImageLayout::ColorAttachmentOptimal, + ImageLayout::TransferSrcOptimal, + ) + .wait(None) + .unwrap(); + + self.target_layout = ImageLayout::TransferSrcOptimal; + } +} + pub struct ScreenRenderer { capture: Box, - resolution: (i32, i32), receiver: Option>, - view: Option>, + pipeline: Option, + last_frame: Option>, } impl ScreenRenderer { @@ -114,9 +217,9 @@ impl ScreenRenderer { }; Some(ScreenRenderer { capture: Box::new(capture), - resolution: output.size, receiver: None, - view: None, + pipeline: None, + last_frame: None, }) } @@ -132,15 +235,11 @@ impl ScreenRenderer { Some(ScreenRenderer { capture: Box::new(capture), - resolution: output.size, receiver: None, - view: None, + pipeline: None, + last_frame: None, }) } - - pub fn new_xshm() -> ScreenRenderer { - todo!() - } } impl OverlayRenderer for ScreenRenderer { @@ -157,28 +256,18 @@ impl OverlayRenderer for ScreenRenderer { match frame { WlxFrame::Dmabuf(frame) => { if let Ok(new) = app.graphics.dmabuf_texture(frame) { - if let Some(current) = self.view.as_ref() { - if current.image().inner().image.handle().as_raw() - == new.inner().image.handle().as_raw() - { - return; - } - } - app.graphics - .transition_layout( - new.inner().image.clone(), - ImageLayout::Undefined, - ImageLayout::TransferSrcOptimal, - ) - .wait(None) - .unwrap(); - self.view = Some(ImageView::new_default(new).unwrap()); + let pipeline = self + .pipeline + .get_or_insert_with(|| ScreenPipeline::new(app.graphics.clone(), &new)); + + pipeline.render(new); + self.last_frame = Some(pipeline.view.clone()); } } - WlxFrame::MemFd(frame) => { + WlxFrame::MemFd(_frame) => { todo!() } - WlxFrame::MemPtr(frame) => { + WlxFrame::MemPtr(_frame) => { todo!() } _ => {} @@ -193,7 +282,7 @@ impl OverlayRenderer for ScreenRenderer { self.capture.resume(); } fn view(&mut self) -> Option> { - self.view.as_ref().and_then(|v| Some(v.clone())) + self.last_frame.take() } } @@ -202,21 +291,25 @@ where O: Default, { let output = &wl.outputs[idx]; - info!( + log::info!( "{}: Res {}x{} Size {:?} Pos {:?}", - output.name, output.size.0, output.size.1, output.logical_size, output.logical_pos, + output.name, + output.size.0, + output.size.1, + output.logical_size, + output.logical_pos, ); let size = (output.size.0, output.size.1); let mut capture: Option = None; if session.capture_method == "auto" && wl.maybe_wlr_dmabuf_mgr.is_some() { - info!("{}: Using Wlr DMA-Buf", &output.name); + log::info!("{}: Using Wlr DMA-Buf", &output.name); capture = ScreenRenderer::new_wlr(output); } if capture.is_none() { - info!("{}: Using Pipewire capture", &output.name); + log::info!("{}: Using Pipewire capture", &output.name); let file_name = format!("{}.token", &output.name); let full_path = Path::new(&session.config_path).join(file_name); let token = std::fs::read_to_string(full_path).ok(); @@ -246,6 +339,20 @@ where _ => 0., }; + let interaction_transform = if output.size.0 >= output.size.1 { + Affine2::from_translation(Vec2 { x: 0.5, y: 0.5 }) + * Affine2::from_scale(Vec2 { + x: 1., + y: output.size.0 as f32 / output.size.1 as f32, + }) + } else { + Affine2::from_translation(Vec2 { x: 0.5, y: 0.5 }) + * Affine2::from_scale(Vec2 { + x: output.size.1 as f32 / output.size.0 as f32, + y: 1., + }) + }; + Some(OverlayData { state: OverlayState { name: output.name.clone(), @@ -254,13 +361,14 @@ where show_hide: true, grabbable: true, spawn_rotation: Quat::from_axis_angle(axis, angle), + interaction_transform, ..Default::default() }, backend, ..Default::default() }) } else { - warn!("{}: Will not be used", &output.name); + log::warn!("{}: Will not be used", &output.name); None } } diff --git a/src/overlays/watch.rs b/src/overlays/watch.rs index 7f66ac9..8663b35 100644 --- a/src/overlays/watch.rs +++ b/src/overlays/watch.rs @@ -76,7 +76,7 @@ where let button_width = 360. / num_buttons as f32; let mut button_x = 40.; - let keyboard = canvas.button(button_x + 2., 162., button_width - 4., 36., "Kbd".into()); + let keyboard = canvas.button(button_x + 2., 162., button_width - 4., 36., "kbd".into()); keyboard.state = Some(WatchButtonState { pressed_at: Instant::now(), scr_idx: 0, @@ -95,14 +95,14 @@ where < 2000 { app.tasks.enqueue(TaskType::Overlay( - OverlaySelector::Name("Kbd".into()), + OverlaySelector::Name("kbd".into()), Box::new(|_app, o| { o.want_visible = !o.want_visible; }), )); } else { app.tasks.enqueue(TaskType::Overlay( - OverlaySelector::Name("Kbd".into()), + OverlaySelector::Name("kbd".into()), Box::new(|app, o| { o.reset(app); }), diff --git a/src/state.rs b/src/state.rs index c2df4c6..31e2e84 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,7 +1,6 @@ use std::{env::VarError, path::Path, sync::Arc}; use glam::{Quat, Vec3}; -use log::warn; use vulkano::{ device::{physical::PhysicalDevice, DeviceExtensions}, format::Format, @@ -55,6 +54,7 @@ pub struct AppSession { pub screen_flip_h: bool, pub screen_flip_v: bool, pub screen_invert_color: bool, + pub screen_max_res: [u32; 2], pub watch_hand: usize, pub watch_pos: Vec3, @@ -77,7 +77,7 @@ impl AppSession { let config_path = std::env::var("XDG_CONFIG_HOME") .or_else(|_| std::env::var("HOME").map(|home| format!("{}/.config", home))) .or_else(|_| { - warn!("Err: $XDG_CONFIG_HOME and $HOME are not set, using /tmp/wlxoverlay"); + log::warn!("Err: $XDG_CONFIG_HOME and $HOME are not set, using /tmp/wlxoverlay"); Ok::("/tmp".to_string()) }) .map(|config| Path::new(&config).join("wlxoverlay")) @@ -95,6 +95,7 @@ impl AppSession { screen_flip_h: false, screen_flip_v: false, screen_invert_color: false, + screen_max_res: [2560, 1440], capture_method: "auto".to_string(), primary_hand: 1, watch_hand: 1,