From 3d6ba5206e0bcbfad97c534953c6fefe1fc52d01 Mon Sep 17 00:00:00 2001 From: Putta Khunchalee Date: Thu, 16 Jan 2025 02:57:48 +0700 Subject: [PATCH] Creates VkSurfaceKHR manually (#1249) --- Cargo.lock | 59 +---------------------------- gui/Cargo.toml | 5 +-- gui/src/graphics/metal/window.rs | 6 +-- gui/src/graphics/vulkan/engine.rs | 62 ++++++++++++++++++++++++++++--- gui/src/graphics/vulkan/mod.rs | 21 +++++++---- gui/src/rt/mod.rs | 4 +- gui/src/ui/backend/mod.rs | 5 +-- gui/src/ui/backend/wayland.rs | 5 ++- 8 files changed, 82 insertions(+), 85 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a77189dfc..c89d92908 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -186,17 +186,6 @@ dependencies = [ "libloading 0.7.4", ] -[[package]] -name = "ash-window" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b912285a7c29f3a8f87ca6f55afc48768624e5e33ec17dbd2f2075903f5e35ab" -dependencies = [ - "ash", - "raw-window-handle 0.5.2", - "raw-window-metal 0.3.2", -] - [[package]] name = "ashpd" version = "0.9.2" @@ -739,36 +728,6 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cbd0f76e066e64fdc5631e3bb46381254deab9ef1158292f27c8c57e3bf3fe59" -[[package]] -name = "cocoa" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c" -dependencies = [ - "bitflags 1.3.2", - "block", - "cocoa-foundation", - "core-foundation 0.9.4", - "core-graphics 0.23.2", - "foreign-types", - "libc", - "objc", -] - -[[package]] -name = "cocoa-foundation" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" -dependencies = [ - "bitflags 1.3.2", - "block", - "core-foundation 0.9.4", - "core-graphics-types 0.1.3", - "libc", - "objc", -] - [[package]] name = "codemap" version = "0.1.3" @@ -1707,7 +1666,6 @@ dependencies = [ "anstyle-parse", "applevisor-sys", "ash", - "ash-window", "ashpd", "async-net", "bitfield-struct", @@ -1732,7 +1690,6 @@ dependencies = [ "obfw", "objc", "open", - "raw-window-handle 0.5.2", "raw-window-handle 0.6.2", "redb", "rustc-hash 2.1.0", @@ -2012,7 +1969,7 @@ dependencies = [ "once_cell", "pin-weak", "raw-window-handle 0.6.2", - "raw-window-metal 1.0.0", + "raw-window-metal", "scoped-tls-hkt", "skia-safe", "softbuffer", @@ -2645,7 +2602,6 @@ dependencies = [ "log", "ndk-sys", "num_enum", - "raw-window-handle 0.5.2", "raw-window-handle 0.6.2", "thiserror 1.0.66", ] @@ -3282,18 +3238,6 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" -[[package]] -name = "raw-window-metal" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac4ea493258d54c24cb46aa9345d099e58e2ea3f30dd63667fc54fc892f18e76" -dependencies = [ - "cocoa", - "core-graphics 0.23.2", - "objc", - "raw-window-handle 0.5.2", -] - [[package]] name = "raw-window-metal" version = "1.0.0" @@ -4979,7 +4923,6 @@ dependencies = [ "orbclient", "percent-encoding", "pin-project", - "raw-window-handle 0.5.2", "raw-window-handle 0.6.2", "redox_syscall 0.4.1", "rustix", diff --git a/gui/Cargo.toml b/gui/Cargo.toml index adbdad72e..d7848d122 100644 --- a/gui/Cargo.toml +++ b/gui/Cargo.toml @@ -28,7 +28,6 @@ obfw = { git = "https://github.com/obhq/firmware-dumper.git", rev = "64787fdc048 ] } open = { version = "5.3.1" } raw-window-handle = "0.6.2" -rwh05 = { package = "raw-window-handle", version = "0.5.2" } redb = "2.2.0" rustc-hash = "2.1.0" serde = { version = "1.0.209", features = ["derive"] } @@ -41,7 +40,7 @@ slint = { version = "=1.9.0", features = [ ], default-features = false } thiserror = "2.0.3" uuid = { version = "1.11.0", features = ["serde", "v4"] } -winit = { version = "0.30.5", features = ["rwh_05"] } +winit = { version = "0.30.5", features = ["rwh_06"] } [target.'cfg(target_arch = "aarch64")'.dependencies] aarch64 = { path = "../arch/aarch64" } @@ -51,7 +50,6 @@ x86-64 = { path = "../arch/x86-64" } [target.'cfg(target_os = "linux")'.dependencies] ash = { version = "0.37.3", features = ["linked"], default-features = false } -ash-window = "=0.12.0" ashpd = { version = "0.9.2", features = [ "async-std", "raw_handle", @@ -68,7 +66,6 @@ xdg = "2.5.2" [target.'cfg(target_os = "windows")'.dependencies] ash = { version = "0.37.3", features = ["linked"], default-features = false } -ash-window = "=0.12.0" i-slint-renderer-skia = { version = "=1.9.0", features = ["vulkan"] } windows-sys = { version = "0.59.0", features = [ "Win32", diff --git a/gui/src/graphics/metal/window.rs b/gui/src/graphics/metal/window.rs index 15a38091e..6a807afb7 100644 --- a/gui/src/graphics/metal/window.rs +++ b/gui/src/graphics/metal/window.rs @@ -3,7 +3,7 @@ use crate::rt::{Hook, WindowHandler}; use metal::{CAMetalLayer, MetalLayer}; use objc::runtime::{Object, NO, YES}; use objc::{msg_send, sel, sel_impl}; -use rwh05::{HasRawWindowHandle, RawWindowHandle}; +use raw_window_handle::{HasWindowHandle, RawWindowHandle}; use std::error::Error; use std::ptr::null_mut; use std::rc::Rc; @@ -27,8 +27,8 @@ impl MetalWindow { window: Window, ) -> Result, Box> { let layer = unsafe { engine.create_layer() }; - let view = match window.raw_window_handle() { - RawWindowHandle::AppKit(v) => v.ns_view as *mut Object, + let view = match window.window_handle().unwrap().as_raw() { + RawWindowHandle::AppKit(v) => v.ns_view.as_ptr() as *mut Object, _ => unreachable!(), }; diff --git a/gui/src/graphics/vulkan/engine.rs b/gui/src/graphics/vulkan/engine.rs index 74bd2be2f..7ae043ae9 100644 --- a/gui/src/graphics/vulkan/engine.rs +++ b/gui/src/graphics/vulkan/engine.rs @@ -2,10 +2,13 @@ use super::{GraphicsError, VulkanBuilder}; use crate::graphics::Graphics; use crate::profile::Profile; -use ash::vk::{DeviceCreateInfo, DeviceQueueCreateInfo, QueueFlags, SurfaceKHR}; +use ash::extensions::khr::{WaylandSurface, Win32Surface, XcbSurface, XlibSurface}; +use ash::vk::{ + DeviceCreateInfo, DeviceQueueCreateInfo, QueueFlags, SurfaceKHR, WaylandSurfaceCreateInfoKHR, + Win32SurfaceCreateInfoKHR, XcbSurfaceCreateInfoKHR, XlibSurfaceCreateInfoKHR, +}; use ash::Device; -use ash_window::create_surface; -use rwh05::{HasRawDisplayHandle, HasRawWindowHandle}; +use raw_window_handle::{HasDisplayHandle, HasWindowHandle, RawDisplayHandle, RawWindowHandle}; use winit::window::Window; /// Implementation of [`Graphics`] using Vulkan. @@ -51,10 +54,57 @@ impl Vulkan { /// # Safety /// The returned [`SurfaceKHR`] must be destroyed before `win` and this [`Vulkan`]. pub unsafe fn create_surface(&self, win: &Window) -> Result { - let dh = win.raw_display_handle(); - let wh = win.raw_window_handle(); + let e = &self.builder.entry; + let i = &self.builder.instance; + let w = win.window_handle().unwrap(); - create_surface(&self.builder.entry, &self.builder.instance, dh, wh, None) + match w.as_ref() { + RawWindowHandle::UiKit(_) + | RawWindowHandle::AppKit(_) + | RawWindowHandle::Web(_) + | RawWindowHandle::WebCanvas(_) + | RawWindowHandle::WebOffscreenCanvas(_) => { + unreachable!() + } + RawWindowHandle::Xlib(v) => { + let c = XlibSurfaceCreateInfoKHR::builder() + .dpy(match win.display_handle().unwrap().as_ref() { + RawDisplayHandle::Xlib(v) => v.display.unwrap().as_ptr().cast(), + _ => unreachable!(), + }) + .window(v.window); + + XlibSurface::new(e, i).create_xlib_surface(&c, None) + } + RawWindowHandle::Xcb(v) => { + let c = XcbSurfaceCreateInfoKHR::builder() + .connection(match win.display_handle().unwrap().as_ref() { + RawDisplayHandle::Xcb(v) => v.connection.unwrap().as_ptr(), + _ => unreachable!(), + }) + .window(v.window.get()); + + XcbSurface::new(e, i).create_xcb_surface(&c, None) + } + RawWindowHandle::Wayland(v) => { + let c = WaylandSurfaceCreateInfoKHR::builder() + .display(match win.display_handle().unwrap().as_ref() { + RawDisplayHandle::Wayland(v) => v.display.as_ptr(), + _ => unreachable!(), + }) + .surface(v.surface.as_ptr()); + + WaylandSurface::new(e, i).create_wayland_surface(&c, None) + } + RawWindowHandle::Win32(v) => { + let c = Win32SurfaceCreateInfoKHR::builder() + .hinstance(v.hinstance.unwrap().get() as _) + .hwnd(v.hwnd.get() as _); + + Win32Surface::new(e, i).create_win32_surface(&c, None) + } + _ => todo!(), + } } /// # Safety diff --git a/gui/src/graphics/vulkan/mod.rs b/gui/src/graphics/vulkan/mod.rs index efe2b1bb1..9833b59f0 100644 --- a/gui/src/graphics/vulkan/mod.rs +++ b/gui/src/graphics/vulkan/mod.rs @@ -7,7 +7,7 @@ use crate::rt::{create_window, raw_display_handle}; use ash::extensions::khr::Surface; use ash::vk::{ApplicationInfo, InstanceCreateInfo, QueueFlags, API_VERSION_1_3}; use ash::{Entry, Instance}; -use ash_window::enumerate_required_extensions; +use raw_window_handle::RawDisplayHandle; use std::ffi::CStr; use std::mem::ManuallyDrop; use std::rc::Rc; @@ -21,8 +21,18 @@ mod window; pub fn builder() -> Result { // Get required extensions for window. - let exts = enumerate_required_extensions(raw_display_handle()) - .map_err(GraphicsError::GetExtensionsForWindow)?; + let mut exts = vec![c"VK_KHR_surface".as_ptr()]; + + match raw_display_handle() { + RawDisplayHandle::UiKit(_) | RawDisplayHandle::AppKit(_) | RawDisplayHandle::Web(_) => { + unreachable!() + } + RawDisplayHandle::Xlib(_) => exts.push(c"VK_KHR_xlib_surface".as_ptr()), + RawDisplayHandle::Xcb(_) => exts.push(c"VK_KHR_xcb_surface".as_ptr()), + RawDisplayHandle::Wayland(_) => exts.push(c"VK_KHR_wayland_surface".as_ptr()), + RawDisplayHandle::Windows(_) => exts.push(c"VK_KHR_win32_surface".as_ptr()), + _ => todo!(), + } // Setup application info. let mut app = ApplicationInfo::default(); @@ -40,7 +50,7 @@ pub fn builder() -> Result { let info = InstanceCreateInfo::builder() .application_info(&app) .enabled_layer_names(&layers) - .enabled_extension_names(exts); + .enabled_extension_names(&exts); // Create Vulkan instance. let entry = Entry::linked(); @@ -153,9 +163,6 @@ impl super::PhysicalDevice for PhysicalDevice { /// Represents an error when operation on Vulkan fails. #[derive(Debug, Error)] pub enum GraphicsError { - #[error("couldn't get required Vulkan extensions for window")] - GetExtensionsForWindow(#[source] ash::vk::Result), - #[error("couldn't create Vulkan instance")] CreateInstance(#[source] ash::vk::Result), diff --git a/gui/src/rt/mod.rs b/gui/src/rt/mod.rs index f9b8f1bce..76edb18a4 100644 --- a/gui/src/rt/mod.rs +++ b/gui/src/rt/mod.rs @@ -5,8 +5,8 @@ pub use self::window::*; use self::context::Context; use self::task::TaskList; +use raw_window_handle::{HasDisplayHandle, RawDisplayHandle}; use rustc_hash::FxHashMap; -use rwh05::{HasRawDisplayHandle, RawDisplayHandle}; use std::any::{Any, TypeId}; use std::cell::Cell; use std::collections::HashMap; @@ -141,7 +141,7 @@ pub fn yield_now() -> impl Future { /// # Panics /// If called from the other thread than main thread. pub fn raw_display_handle() -> RawDisplayHandle { - Context::with(|cx| cx.el.raw_display_handle()) + Context::with(|cx| cx.el.display_handle().unwrap().as_raw()) } /// You need to call [`register_window()`] after this to receive events for the created window and diff --git a/gui/src/ui/backend/mod.rs b/gui/src/ui/backend/mod.rs index 6e70cc2ae..d59cb9376 100644 --- a/gui/src/ui/backend/mod.rs +++ b/gui/src/ui/backend/mod.rs @@ -5,6 +5,8 @@ pub(super) use self::window::Window; use crate::rt::{create_window, raw_display_handle, WindowHandler}; use i_slint_core::graphics::RequestedGraphicsAPI; use i_slint_renderer_skia::SkiaRenderer; +#[cfg(target_os = "linux")] +use raw_window_handle::RawDisplayHandle; use rustc_hash::FxHashMap; use slint::platform::{ duration_until_next_timer_update, update_timers_and_animations, SetPlatformError, WindowAdapter, @@ -40,9 +42,6 @@ impl SlintBackend { /// # Safety /// The returned [`SlintBackend`] must not outlive the event loop. pub unsafe fn new() -> Result { - #[cfg(target_os = "linux")] - use rwh05::RawDisplayHandle; - let mut b = Self { #[cfg(target_os = "linux")] wayland: None, diff --git a/gui/src/ui/backend/wayland.rs b/gui/src/ui/backend/wayland.rs index 15b3691af..a6bb055ec 100644 --- a/gui/src/ui/backend/wayland.rs +++ b/gui/src/ui/backend/wayland.rs @@ -1,4 +1,5 @@ use super::BackendError; +use raw_window_handle::WaylandDisplayHandle; use std::cell::RefCell; use std::future::Future; use std::hint::unreachable_unchecked; @@ -25,9 +26,9 @@ pub struct Wayland { impl Wayland { /// # Safety /// `display` must outlive the returned [`Wayland`]. - pub unsafe fn new(display: rwh05::WaylandDisplayHandle) -> Result { + pub unsafe fn new(display: WaylandDisplayHandle) -> Result { // Get wayland connection. - let backend = Backend::from_foreign_display(display.display.cast()); + let backend = Backend::from_foreign_display(display.display.as_ptr().cast()); let conn = Connection::from_backend(backend); // Get global objects.