From e2def4734dd0782ef19cdd37b10336a06c236b4b Mon Sep 17 00:00:00 2001 From: marc2332 Date: Sun, 25 Aug 2024 12:20:13 +0200 Subject: [PATCH 1/6] feat: Graphics Drivers --- crates/renderer/src/renderer.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/crates/renderer/src/renderer.rs b/crates/renderer/src/renderer.rs index c45cec97a..e2fbad5d9 100644 --- a/crates/renderer/src/renderer.rs +++ b/crates/renderer/src/renderer.rs @@ -280,13 +280,8 @@ impl<'a, State: Clone> ApplicationHandler for DesktopRenderer<'a, app.measure_layout_on_next_render = false; } - if app.init_accessibility_on_next_render { - app.init_accessibility(window); - app.init_accessibility_on_next_render = false; - } - graphics_driver.make_current(); - + app.render( &self.hovered_node, window_config.background, From 7f5f71e125c09dba54618a7a64bf3194e14a1c77 Mon Sep 17 00:00:00 2001 From: reya Date: Wed, 4 Sep 2024 11:10:15 +0700 Subject: [PATCH 2/6] feat: add vulkan driver --- Cargo.toml | 60 +++- crates/engine/src/skia.rs | 97 ++----- crates/renderer/Cargo.toml | 5 +- crates/renderer/src/drivers/mod.rs | 21 +- crates/renderer/src/drivers/vulkan.rs | 403 ++++++++++++++++++++++++++ 5 files changed, 489 insertions(+), 97 deletions(-) create mode 100644 crates/renderer/src/drivers/vulkan.rs diff --git a/Cargo.toml b/Cargo.toml index d7157b343..0d7891b8d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,23 @@ version = "0.0.0" edition = "2021" [workspace] -members = ["crates/renderer", "crates/state", "crates/freya", "crates/elements", "crates/components", "crates/hooks", "crates/common", "crates/core", "crates/testing", "crates/devtools", "crates/torin", "crates/engine", "./examples/installer", "crates/native-core", "crates/native-core-macro"] +members = [ + "crates/renderer", + "crates/state", + "crates/freya", + "crates/elements", + "crates/components", + "crates/hooks", + "crates/common", + "crates/core", + "crates/testing", + "crates/devtools", + "crates/torin", + "crates/engine", + "./examples/installer", + "crates/native-core", + "crates/native-core-macro", +] [features] tracing-subscriber = ["freya/tracing-subscriber"] @@ -42,31 +58,55 @@ torin = { path = "crates/torin", version = "0.2" } freya-native-core-macro = { path = "crates/native-core-macro", version = "0.2" } freya-native-core = { path = "crates/native-core", version = "0.2" } -dioxus = { version = "0.5", default-features = false, features = ["macro", "signals", "hooks"]} +dioxus = { version = "0.5", default-features = false, features = [ + "macro", + "signals", + "hooks", +] } dioxus-rsx = { version = "0.5", features = ["hot_reload"] } dioxus-core-macro = { version = "0.5" } dioxus-hooks = { version = "0.5" } dioxus-signals = { version = "0.5" } dioxus-core = { version = "0.5" } -dioxus-hot-reload = { version = "0.5", features = ["file_watcher"], default-features = false } +dioxus-hot-reload = { version = "0.5", features = [ + "file_watcher", +], default-features = false } dioxus-router = { version = "0.5", default-features = false } -dioxus-sdk = { version = "0.5", features = ["clipboard"]} +dioxus-sdk = { version = "0.5", features = ["clipboard"] } -skia-safe = { version = "0.75.0", features = ["gl", "textlayout", "svg"] } +skia-safe = { version = "0.75.0", features = [ + "gl", + "vulkan", + "egl", + "x11", + "wayland", + "textlayout", + "svg", + "webp", +] } gl = "0.14.0" glutin = "0.32.0" glutin-winit = "0.5.0" raw-window-handle = "0.6.0" winit = "0.30.0" -tokio = { version = "1.33.0", features = ["sync", "rt-multi-thread", "time", "macros"] } -accesskit = { version = "0.16.0", features = ["serde"]} +tokio = { version = "1.33.0", features = [ + "sync", + "rt-multi-thread", + "time", + "macros", +] } +accesskit = { version = "0.16.0", features = ["serde"] } accesskit_winit = "0.22.0" -shipyard = { version = "0.6.2", features = ["proc", "std", "parallel"], default-features = false } +shipyard = { version = "0.6.2", features = [ + "proc", + "std", + "parallel", +], default-features = false } smallvec = "1.13.1" euclid = "0.22.9" -uuid = { version = "1.4.1", features = ["v4"]} +uuid = { version = "1.4.1", features = ["v4"] } futures-util = "0.3.30" futures-task = "0.3.30" tracing = "0.1" @@ -75,7 +115,7 @@ rustc-hash = "2.0.0" [dev-dependencies] skia-safe = { workspace = true } -tokio = { workspace = true, features = ["fs"]} +tokio = { workspace = true, features = ["fs"] } dioxus = { workspace = true } freya = { workspace = true } freya-core = { workspace = true } diff --git a/crates/engine/src/skia.rs b/crates/engine/src/skia.rs index f3524415a..06af407db 100644 --- a/crates/engine/src/skia.rs +++ b/crates/engine/src/skia.rs @@ -1,27 +1,18 @@ pub use skia_safe::{ - font_style::{ - Slant, - Weight, - Width, - }, + font_style::{Slant, Weight, Width}, gpu::{ - backend_render_targets, - direct_contexts, - gl::{ - Format, - FramebufferInfo, - Interface, - }, + backend_render_targets, direct_contexts, + gl::{Format, FramebufferInfo, Interface}, surfaces::wrap_backend_render_target, - BackendRenderTarget, - DirectContext, - RecordingContext, - SurfaceOrigin, + vk::{ + Alloc, BackendContext, Format as VkFormat, GetProcOf, ImageInfo as VkImageInfo, + ImageLayout, ImageTiling, + }, + BackendRenderTarget, DirectContext, RecordingContext, SurfaceOrigin, }, gradient_shader::GradientShaderColors, graphics::{ - set_resource_cache_single_allocation_byte_limit, - set_resource_cache_total_bytes_limit, + set_resource_cache_single_allocation_byte_limit, set_resource_cache_total_bytes_limit, }, path::ArcSize, rrect::Corner, @@ -29,66 +20,14 @@ pub use skia_safe::{ surfaces::raster_n32_premul, svg, textlayout::{ - paragraph::GlyphClusterInfo, - Decoration, - FontCollection, - FontFeature, - LineMetrics, - Paragraph, - ParagraphBuilder, - ParagraphStyle, - PlaceholderStyle, - PositionWithAffinity, - RectHeightStyle, - RectWidthStyle, - StrutStyle, - TextAlign, - TextBaseline, - TextBox, - TextDecoration, - TextDecorationStyle, - TextDirection, - TextHeightBehavior, - TextIndex, - TextRange, - TextShadow, - TextStyle, - TypefaceFontProvider, + paragraph::GlyphClusterInfo, Decoration, FontCollection, FontFeature, LineMetrics, + Paragraph, ParagraphBuilder, ParagraphStyle, PlaceholderStyle, PositionWithAffinity, + RectHeightStyle, RectWidthStyle, StrutStyle, TextAlign, TextBaseline, TextBox, + TextDecoration, TextDecorationStyle, TextDirection, TextHeightBehavior, TextIndex, + TextRange, TextShadow, TextStyle, TypefaceFontProvider, }, - Bitmap, - BlurStyle, - Canvas, - ClipOp, - Color, - ColorSpace, - ColorType, - Data, - EncodedImageFormat, - FilterMode, - FontArguments, - FontMgr, - FontStyle, - IPoint, - IRect, - Image, - ImageInfo, - MaskFilter, - Matrix, - Paint, - PaintStyle, - Path, - PathDirection, - Point, - RRect, - Rect, - RuntimeEffect, - SamplingOptions, - Shader, - Surface, - TileMode, - Typeface, - HSV, - M44, - RGB, - V3, + Bitmap, BlurStyle, Canvas, ClipOp, Color, ColorSpace, ColorType, Data, EncodedImageFormat, + FilterMode, FontArguments, FontMgr, FontStyle, IPoint, IRect, Image, ImageInfo, MaskFilter, + Matrix, Paint, PaintStyle, Path, PathDirection, Point, RRect, Rect, RuntimeEffect, + SamplingOptions, Shader, Surface, TileMode, Typeface, HSV, M44, RGB, V3, }; diff --git a/crates/renderer/Cargo.toml b/crates/renderer/Cargo.toml index ec243f9fe..7f5ea543b 100644 --- a/crates/renderer/Cargo.toml +++ b/crates/renderer/Cargo.toml @@ -40,10 +40,13 @@ winit = { workspace = true } accesskit = { workspace = true } accesskit_winit = { workspace = true } tracing = { workspace = true } -futures-task ={ workspace = true } +futures-task = { workspace = true } futures-util = { workspace = true } itertools = "0.13.0" uuid = { workspace = true } image = "0.25.0" pin-utils = "0.1.0" + +ash = { version = "^0.37.2" } +vulkano = { version = "^0.34.0" } diff --git a/crates/renderer/src/drivers/mod.rs b/crates/renderer/src/drivers/mod.rs index b0accda04..7bfb214d1 100644 --- a/crates/renderer/src/drivers/mod.rs +++ b/crates/renderer/src/drivers/mod.rs @@ -1,21 +1,22 @@ mod gl; +mod vulkan; -use freya_engine::prelude::Surface as SkiaSurface; pub use gl::*; + +use freya_engine::prelude::Surface as SkiaSurface; use glutin::surface::GlSurface; +use vulkan::VulkanDriver; use winit::{ dpi::PhysicalSize, event_loop::ActiveEventLoop, - window::{ - Window, - WindowAttributes, - }, + window::{Window, WindowAttributes}, }; use crate::LaunchConfig; pub enum GraphicsDriver { OpenGl(OpenGLDriver), + Vulkan(VulkanDriver), } impl GraphicsDriver { @@ -24,13 +25,15 @@ impl GraphicsDriver { window_attributes: WindowAttributes, config: &LaunchConfig, ) -> (Self, Window, SkiaSurface) { - let (driver, window, surface) = OpenGLDriver::new(event_loop, window_attributes, config); - (Self::OpenGl(driver), window, surface) + let (driver, window, surface) = VulkanDriver::new(event_loop, window_attributes, config); + + (Self::Vulkan(driver), window, surface) } pub fn make_current(&mut self) { match self { Self::OpenGl(gl) => gl.make_current(), + Self::Vulkan(_) => {} } } @@ -40,12 +43,16 @@ impl GraphicsDriver { gl.gr_context.flush_and_submit(); gl.gl_surface.swap_buffers(&gl.gl_context).unwrap(); } + Self::Vulkan(vk) => { + vk.gr_context.flush_and_submit(); + } } } pub fn resize(&mut self, size: PhysicalSize) -> (SkiaSurface, SkiaSurface) { match self { Self::OpenGl(gl) => gl.resize(size), + Self::Vulkan(vk) => vk.resize(size), } } } diff --git a/crates/renderer/src/drivers/vulkan.rs b/crates/renderer/src/drivers/vulkan.rs new file mode 100644 index 000000000..88bbdf9b7 --- /dev/null +++ b/crates/renderer/src/drivers/vulkan.rs @@ -0,0 +1,403 @@ +use freya_engine::prelude::{ + backend_render_targets, direct_contexts, wrap_backend_render_target, Alloc, BackendContext, + Canvas, ColorType, DirectContext, GetProcOf, ImageLayout, ImageTiling, Surface as SkiaSurface, + SurfaceOrigin, VkFormat, VkImageInfo, +}; +use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; +use std::{ + cell::{Cell, RefCell}, + sync::Arc, +}; +use vulkano::{ + device::{ + physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Queue, + QueueCreateInfo, QueueFlags, + }, + image::{view::ImageView, Image, ImageUsage}, + instance::{Instance, InstanceCreateFlags, InstanceCreateInfo, InstanceExtensions}, + swapchain::{Surface, Swapchain, SwapchainCreateInfo, SwapchainPresentInfo}, + sync::{self, GpuFuture}, + Handle, Validated, VulkanError, VulkanLibrary, VulkanObject, +}; +use winit::{ + dpi::PhysicalSize, + event_loop::ActiveEventLoop, + window::{Window, WindowAttributes}, +}; + +use crate::{size::WinitSize, LaunchConfig}; + +/// Graphics driver using Vulkan. +pub struct VulkanDriver { + pub(crate) gr_context: DirectContext, + pub(crate) recreate_swapchain: Cell, + pub(crate) device: Arc, + pub(crate) previous_frame_end: RefCell>>, + pub(crate) queue: Arc, + pub(crate) swapchain: RefCell>, + pub(crate) swapchain_images: RefCell>>, + pub(crate) swapchain_image_views: RefCell>>, +} + +impl VulkanDriver { + pub fn new( + event_loop: &ActiveEventLoop, + window_attributes: WindowAttributes, + _config: &LaunchConfig, + ) -> (Self, Window, SkiaSurface) { + let window = event_loop + .create_window(window_attributes) + .expect("Could not create window with Vulkan context"); + + let library = VulkanLibrary::new().expect("Could not create Vulkan library"); + let required_extensions = InstanceExtensions { + khr_surface: true, + mvk_macos_surface: true, + ext_metal_surface: true, + khr_wayland_surface: true, + khr_xlib_surface: true, + khr_xcb_surface: true, + khr_win32_surface: true, + khr_get_surface_capabilities2: true, + khr_get_physical_device_properties2: true, + ..InstanceExtensions::empty() + } + .intersection(library.supported_extensions()); + + let instance = Instance::new( + library.clone(), + InstanceCreateInfo { + flags: InstanceCreateFlags::ENUMERATE_PORTABILITY, + enabled_extensions: required_extensions, + ..Default::default() + }, + ) + .expect("Could not create Vulkan instance"); + + let window_handle = window.window_handle().unwrap(); + let display_handle = window.display_handle().unwrap(); + + let surface = create_surface(&instance, window_handle, display_handle) + .expect("Could not create Vulkan surface"); + + let device_extensions = DeviceExtensions { + khr_swapchain: true, + ..DeviceExtensions::empty() + }; + + let (physical_device, queue_family_index) = instance + .enumerate_physical_devices() + .unwrap() + .filter(|p| p.supported_extensions().contains(&device_extensions)) + .filter_map(|p| { + p.queue_family_properties() + .iter() + .enumerate() + .position(|(i, q)| { + q.queue_flags.intersects(QueueFlags::GRAPHICS) + && p.surface_support(i as u32, &surface).unwrap_or(false) + }) + .map(|i| (p, i as u32)) + }) + .min_by_key(|(p, _)| match p.properties().device_type { + PhysicalDeviceType::DiscreteGpu => 0, + PhysicalDeviceType::IntegratedGpu => 1, + PhysicalDeviceType::VirtualGpu => 2, + PhysicalDeviceType::Cpu => 3, + PhysicalDeviceType::Other => 4, + _ => 5, + }) + .unwrap(); + + let (device, mut queues) = Device::new( + physical_device.clone(), + DeviceCreateInfo { + enabled_extensions: DeviceExtensions { + khr_swapchain: true, + ..DeviceExtensions::empty() + }, + queue_create_infos: vec![QueueCreateInfo { + queue_family_index, + ..Default::default() + }], + ..Default::default() + }, + ) + .unwrap(); + + let size = window.inner_size(); + let queue = queues.next().unwrap(); + + let (swapchain, swapchain_images) = { + let surface_capabilities = device + .physical_device() + .surface_capabilities(&surface, Default::default()) + .unwrap(); + let image_format = vulkano::format::Format::B8G8R8A8_UNORM; + + Swapchain::new( + device.clone(), + surface.clone(), + SwapchainCreateInfo { + min_image_count: surface_capabilities.min_image_count, + image_format, + image_extent: [size.width, size.height], + image_usage: ImageUsage::COLOR_ATTACHMENT, + composite_alpha: surface_capabilities + .supported_composite_alpha + .into_iter() + .next() + .unwrap(), + ..Default::default() + }, + ) + .unwrap() + }; + + let mut swapchain_image_views = Vec::with_capacity(swapchain_images.len()); + + for image in &swapchain_images { + swapchain_image_views.push(ImageView::new_default(image.clone()).unwrap()); + } + + let instance = physical_device.instance(); + let library = instance.library(); + + let get_proc = |of| unsafe { + let result = match of { + GetProcOf::Instance(instance, name) => { + library.get_instance_proc_addr(ash::vk::Instance::from_raw(instance as _), name) + } + GetProcOf::Device(device, name) => (instance.fns().v1_0.get_device_proc_addr)( + ash::vk::Device::from_raw(device as _), + name, + ), + }; + + match result { + Some(f) => f as _, + None => { + //println!("resolve of {} failed", of.name().to_str().unwrap()); + core::ptr::null() + } + } + }; + + let backend_context = unsafe { + BackendContext::new( + instance.handle().as_raw() as _, + physical_device.handle().as_raw() as _, + device.handle().as_raw() as _, + (queue.handle().as_raw() as _, queue.id_within_family() as _), + &get_proc, + ) + }; + + let previous_frame_end = RefCell::new(Some(sync::now(device.clone()).boxed())); + let image_info = VkImageInfo::default(); + let render_target = backend_render_targets::make_vk(size.to_skia(), &image_info); + + let mut gr_context = direct_contexts::make_vulkan(&backend_context, None) + .expect("Could not create direct context"); + + let skia_surface = wrap_backend_render_target( + &mut gr_context, + &render_target, + SurfaceOrigin::TopLeft, + ColorType::BGRA8888, + None, + None, + ) + .expect("Could not create skia surface"); + + let driver = VulkanDriver { + gr_context, + recreate_swapchain: Cell::new(false), + device, + previous_frame_end, + queue, + swapchain: RefCell::new(swapchain), + swapchain_images: RefCell::new(swapchain_images), + swapchain_image_views: RefCell::new(swapchain_image_views), + }; + + (driver, window, skia_surface) + } + + pub fn resize(&mut self, size: PhysicalSize) -> (SkiaSurface, SkiaSurface) { + let gr_context = &mut self.gr_context; + + let device = self.device.clone(); + + self.previous_frame_end + .borrow_mut() + .as_mut() + .unwrap() + .cleanup_finished(); + + let swapchain = self.swapchain.borrow().clone(); + + let (image_index, suboptimal, acquire_future) = + vulkano::swapchain::acquire_next_image(swapchain.clone(), None).unwrap(); + + if suboptimal { + self.recreate_swapchain.set(true); + } + + let width = swapchain.image_extent()[0]; + let width: i32 = width.try_into().unwrap(); + let height = swapchain.image_extent()[1]; + let height: i32 = height.try_into().unwrap(); + + let image_view = self.swapchain_image_views.borrow()[image_index as usize].clone(); + let image_object = image_view.image(); + + let (vk_format, color_type) = (VkFormat::B8G8R8A8_UNORM, ColorType::BGRA8888); + + let alloc = Alloc::default(); + let image_info = &unsafe { + VkImageInfo::new( + image_object.handle().as_raw() as _, + alloc, + ImageTiling::OPTIMAL, + ImageLayout::COLOR_ATTACHMENT_OPTIMAL, + vk_format, + 1, + None, + None, + None, + None, + ) + }; + + let render_target = &backend_render_targets::make_vk((width, height), image_info); + + let mut surface = wrap_backend_render_target( + gr_context, + render_target, + SurfaceOrigin::TopLeft, + color_type, + None, + None, + ) + .expect("Could not create skia surface"); + + let dirty_surface = surface.new_surface_with_dimensions(size.to_skia()).unwrap(); + + gr_context.submit(None); + + let future = self + .previous_frame_end + .borrow_mut() + .take() + .unwrap() + .join(acquire_future) + .then_swapchain_present( + self.queue.clone(), + SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index), + ) + .then_signal_fence_and_flush(); + + match future.map_err(Validated::unwrap) { + Ok(future) => { + *self.previous_frame_end.borrow_mut() = Some(future.boxed()); + } + Err(VulkanError::OutOfDate) => { + self.recreate_swapchain.set(true); + *self.previous_frame_end.borrow_mut() = Some(sync::now(device.clone()).boxed()); + } + Err(_) => { + *self.previous_frame_end.borrow_mut() = Some(sync::now(device.clone()).boxed()); + } + } + + (surface, dirty_surface) + } +} + +fn create_surface( + instance: &Arc, + window_handle: raw_window_handle::WindowHandle<'_>, + display_handle: raw_window_handle::DisplayHandle<'_>, +) -> Result, vulkano::Validated> { + match (window_handle.as_raw(), display_handle.as_raw()) { + #[cfg(target_os = "macos")] + ( + raw_window_handle::RawWindowHandle::AppKit(raw_window_handle::AppKitWindowHandle { + ns_view, + .. + }), + _, + ) => unsafe { + use cocoa::{appkit::NSView, base::id as cocoa_id}; + use objc::runtime::YES; + + let layer = metal::MetalLayer::new(); + layer.set_opaque(false); + layer.set_presents_with_transaction(false); + let view = ns_view.as_ptr() as cocoa_id; + view.setWantsLayer(YES); + view.setLayer(layer.as_ref() as *const _ as _); + Surface::from_metal(instance.clone(), layer.as_ref(), None) + }, + ( + raw_window_handle::RawWindowHandle::Xlib(raw_window_handle::XlibWindowHandle { + window, + .. + }), + raw_window_handle::RawDisplayHandle::Xlib(display), + ) => unsafe { + Surface::from_xlib( + instance.clone(), + display.display.unwrap().as_ptr(), + window, + None, + ) + }, + ( + raw_window_handle::RawWindowHandle::Xcb(raw_window_handle::XcbWindowHandle { + window, + .. + }), + raw_window_handle::RawDisplayHandle::Xcb(raw_window_handle::XcbDisplayHandle { + connection, + .. + }), + ) => unsafe { + Surface::from_xcb( + instance.clone(), + connection.unwrap().as_ptr(), + window.get(), + None, + ) + }, + ( + raw_window_handle::RawWindowHandle::Wayland(raw_window_handle::WaylandWindowHandle { + surface, + .. + }), + raw_window_handle::RawDisplayHandle::Wayland(raw_window_handle::WaylandDisplayHandle { + display, + .. + }), + ) => unsafe { + Surface::from_wayland(instance.clone(), display.as_ptr(), surface.as_ptr(), None) + }, + ( + raw_window_handle::RawWindowHandle::Win32(raw_window_handle::Win32WindowHandle { + hwnd, + hinstance, + .. + }), + _, + ) => unsafe { + Surface::from_win32( + instance.clone(), + hinstance.unwrap().get() as *const std::ffi::c_void, + hwnd.get() as *const std::ffi::c_void, + None, + ) + }, + _ => unimplemented!(), + } +} From 4138027b8307de63fd613c36b542340c1db5bafe Mon Sep 17 00:00:00 2001 From: reya Date: Fri, 6 Sep 2024 15:45:22 +0700 Subject: [PATCH 3/6] update --- crates/renderer/src/drivers/vulkan.rs | 91 +++++++++++++++++++-------- 1 file changed, 66 insertions(+), 25 deletions(-) diff --git a/crates/renderer/src/drivers/vulkan.rs b/crates/renderer/src/drivers/vulkan.rs index 88bbdf9b7..dcc2a473b 100644 --- a/crates/renderer/src/drivers/vulkan.rs +++ b/crates/renderer/src/drivers/vulkan.rs @@ -43,12 +43,14 @@ impl VulkanDriver { pub fn new( event_loop: &ActiveEventLoop, window_attributes: WindowAttributes, - _config: &LaunchConfig, + config: &LaunchConfig, ) -> (Self, Window, SkiaSurface) { let window = event_loop .create_window(window_attributes) .expect("Could not create window with Vulkan context"); + let window_size = window.inner_size(); + let library = VulkanLibrary::new().expect("Could not create Vulkan library"); let required_extensions = InstanceExtensions { khr_surface: true, @@ -65,7 +67,7 @@ impl VulkanDriver { .intersection(library.supported_extensions()); let instance = Instance::new( - library.clone(), + library, InstanceCreateInfo { flags: InstanceCreateFlags::ENUMERATE_PORTABILITY, enabled_extensions: required_extensions, @@ -125,7 +127,6 @@ impl VulkanDriver { ) .unwrap(); - let size = window.inner_size(); let queue = queues.next().unwrap(); let (swapchain, swapchain_images) = { @@ -141,7 +142,7 @@ impl VulkanDriver { SwapchainCreateInfo { min_image_count: surface_capabilities.min_image_count, image_format, - image_extent: [size.width, size.height], + image_extent: [window_size.width, window_size.height], image_usage: ImageUsage::COLOR_ATTACHMENT, composite_alpha: surface_capabilities .supported_composite_alpha @@ -157,21 +158,28 @@ impl VulkanDriver { let mut swapchain_image_views = Vec::with_capacity(swapchain_images.len()); for image in &swapchain_images { - swapchain_image_views.push(ImageView::new_default(image.clone()).unwrap()); + swapchain_image_views.push( + ImageView::new_default(image.clone()) + .expect("Error creating image view for swap chain image"), + ); } - let instance = physical_device.instance(); - let library = instance.library(); + let device_instance = physical_device.instance(); + let device_library = device_instance.library(); let get_proc = |of| unsafe { let result = match of { - GetProcOf::Instance(instance, name) => { - library.get_instance_proc_addr(ash::vk::Instance::from_raw(instance as _), name) + GetProcOf::Instance(device_instance, name) => device_library + .get_instance_proc_addr( + ash::vk::Instance::from_raw(device_instance as _), + name, + ), + GetProcOf::Device(device, name) => { + (device_instance.fns().v1_0.get_device_proc_addr)( + ash::vk::Device::from_raw(device as _), + name, + ) } - GetProcOf::Device(device, name) => (instance.fns().v1_0.get_device_proc_addr)( - ash::vk::Device::from_raw(device as _), - name, - ), }; match result { @@ -185,7 +193,7 @@ impl VulkanDriver { let backend_context = unsafe { BackendContext::new( - instance.handle().as_raw() as _, + device_instance.handle().as_raw() as _, physical_device.handle().as_raw() as _, device.handle().as_raw() as _, (queue.handle().as_raw() as _, queue.id_within_family() as _), @@ -193,22 +201,57 @@ impl VulkanDriver { ) }; + let mut gr_context = direct_contexts::make_vulkan(&backend_context, None) + .expect("Could not create Skia Vulkan context"); + let previous_frame_end = RefCell::new(Some(sync::now(device.clone()).boxed())); - let image_info = VkImageInfo::default(); - let render_target = backend_render_targets::make_vk(size.to_skia(), &image_info); - let mut gr_context = direct_contexts::make_vulkan(&backend_context, None) - .expect("Could not create direct context"); + let (image_index, ..) = + match vulkano::swapchain::acquire_next_image(swapchain.clone(), None) + .map_err(Validated::unwrap) + { + Ok(r) => r, + Err(_) => panic!("Vulkan: failed to acquire next image"), + }; + + let image_view = swapchain_image_views[image_index as usize].clone(); + let image_object = image_view.image(); + + let width = swapchain.image_extent()[0]; + let width: i32 = width.try_into().unwrap(); + let height = swapchain.image_extent()[1]; + let height: i32 = height.try_into().unwrap(); + + let image_info = &unsafe { + VkImageInfo::new( + image_object.handle().as_raw() as _, + Alloc::default(), + ImageTiling::OPTIMAL, + ImageLayout::COLOR_ATTACHMENT_OPTIMAL, + VkFormat::B8G8R8A8_UNORM, + 1, + None, + None, + None, + None, + ) + }; + + let render_target = backend_render_targets::make_vk((width, height), image_info); - let skia_surface = wrap_backend_render_target( + let mut skia_surface = wrap_backend_render_target( &mut gr_context, &render_target, - SurfaceOrigin::TopLeft, + SurfaceOrigin::BottomLeft, ColorType::BGRA8888, None, None, ) - .expect("Could not create skia surface"); + .expect("Could not create Skia surface"); + + skia_surface.canvas().clear(config.window_config.background); + + gr_context.flush_and_submit(); let driver = VulkanDriver { gr_context, @@ -225,8 +268,6 @@ impl VulkanDriver { } pub fn resize(&mut self, size: PhysicalSize) -> (SkiaSurface, SkiaSurface) { - let gr_context = &mut self.gr_context; - let device = self.device.clone(); self.previous_frame_end @@ -273,7 +314,7 @@ impl VulkanDriver { let render_target = &backend_render_targets::make_vk((width, height), image_info); let mut surface = wrap_backend_render_target( - gr_context, + &mut self.gr_context, render_target, SurfaceOrigin::TopLeft, color_type, @@ -284,7 +325,7 @@ impl VulkanDriver { let dirty_surface = surface.new_surface_with_dimensions(size.to_skia()).unwrap(); - gr_context.submit(None); + self.gr_context.flush_and_submit(); let future = self .previous_frame_end From dcd4a3874272c1cb77858307423020a6cd1d6d0f Mon Sep 17 00:00:00 2001 From: marc2332 Date: Sun, 8 Sep 2024 11:46:38 +0200 Subject: [PATCH 4/6] chore: reverse unnecessary changes --- Cargo.toml | 62 +++------------- crates/engine/Cargo.toml | 2 +- crates/engine/src/skia.rs | 102 ++++++++++++++++++++++---- crates/renderer/src/drivers/mod.rs | 8 +- crates/renderer/src/drivers/vulkan.rs | 88 +++++++++++++++++----- crates/renderer/src/renderer.rs | 7 +- 6 files changed, 180 insertions(+), 89 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0d7891b8d..5219bdd1d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,23 +4,7 @@ version = "0.0.0" edition = "2021" [workspace] -members = [ - "crates/renderer", - "crates/state", - "crates/freya", - "crates/elements", - "crates/components", - "crates/hooks", - "crates/common", - "crates/core", - "crates/testing", - "crates/devtools", - "crates/torin", - "crates/engine", - "./examples/installer", - "crates/native-core", - "crates/native-core-macro", -] +members = ["crates/renderer", "crates/state", "crates/freya", "crates/elements", "crates/components", "crates/hooks", "crates/common", "crates/core", "crates/testing", "crates/devtools", "crates/torin", "crates/engine", "./examples/installer", "crates/native-core", "crates/native-core-macro"] [features] tracing-subscriber = ["freya/tracing-subscriber"] @@ -58,55 +42,31 @@ torin = { path = "crates/torin", version = "0.2" } freya-native-core-macro = { path = "crates/native-core-macro", version = "0.2" } freya-native-core = { path = "crates/native-core", version = "0.2" } -dioxus = { version = "0.5", default-features = false, features = [ - "macro", - "signals", - "hooks", -] } +dioxus = { version = "0.5", default-features = false, features = ["macro", "signals", "hooks"]} dioxus-rsx = { version = "0.5", features = ["hot_reload"] } dioxus-core-macro = { version = "0.5" } dioxus-hooks = { version = "0.5" } dioxus-signals = { version = "0.5" } dioxus-core = { version = "0.5" } -dioxus-hot-reload = { version = "0.5", features = [ - "file_watcher", -], default-features = false } +dioxus-hot-reload = { version = "0.5", features = ["file_watcher"], default-features = false } dioxus-router = { version = "0.5", default-features = false } -dioxus-sdk = { version = "0.5", features = ["clipboard"] } +dioxus-sdk = { version = "0.5", features = ["clipboard"]} -skia-safe = { version = "0.75.0", features = [ - "gl", - "vulkan", - "egl", - "x11", - "wayland", - "textlayout", - "svg", - "webp", -] } +skia-safe = { version = "0.75.0", features = ["gl", "textlayout", "svg"] } gl = "0.14.0" glutin = "0.32.0" glutin-winit = "0.5.0" raw-window-handle = "0.6.0" winit = "0.30.0" -tokio = { version = "1.33.0", features = [ - "sync", - "rt-multi-thread", - "time", - "macros", -] } -accesskit = { version = "0.16.0", features = ["serde"] } +tokio = { version = "1.33.0", features = ["sync", "rt-multi-thread", "time", "macros"] } +accesskit = { version = "0.16.0", features = ["serde"]} accesskit_winit = "0.22.0" -shipyard = { version = "0.6.2", features = [ - "proc", - "std", - "parallel", -], default-features = false } +shipyard = { version = "0.6.2", features = ["proc", "std", "parallel"], default-features = false } smallvec = "1.13.1" euclid = "0.22.9" -uuid = { version = "1.4.1", features = ["v4"] } +uuid = { version = "1.4.1", features = ["v4"]} futures-util = "0.3.30" futures-task = "0.3.30" tracing = "0.1" @@ -115,7 +75,7 @@ rustc-hash = "2.0.0" [dev-dependencies] skia-safe = { workspace = true } -tokio = { workspace = true, features = ["fs"] } +tokio = { workspace = true, features = ["fs"]} dioxus = { workspace = true } freya = { workspace = true } freya-core = { workspace = true } @@ -137,4 +97,4 @@ bytes = "1.5.0" [profile.release] lto = true -opt-level = 3 +opt-level = 3 \ No newline at end of file diff --git a/crates/engine/Cargo.toml b/crates/engine/Cargo.toml index a8ab05c3f..ade452aa3 100644 --- a/crates/engine/Cargo.toml +++ b/crates/engine/Cargo.toml @@ -27,4 +27,4 @@ glutin = { workspace = true } [target."cfg(target_os = \"linux\")".dependencies.skia-safe] workspace = true optional = true -features = ["gl", "textlayout", "svg", "x11", "wayland"] +features = ["gl", "vulkan", "textlayout", "svg", "x11", "wayland"] diff --git a/crates/engine/src/skia.rs b/crates/engine/src/skia.rs index 06af407db..c9aa8b331 100644 --- a/crates/engine/src/skia.rs +++ b/crates/engine/src/skia.rs @@ -1,18 +1,36 @@ pub use skia_safe::{ - font_style::{Slant, Weight, Width}, + font_style::{ + Slant, + Weight, + Width, + }, gpu::{ - backend_render_targets, direct_contexts, - gl::{Format, FramebufferInfo, Interface}, + backend_render_targets, + direct_contexts, + gl::{ + Format, + FramebufferInfo, + Interface, + }, surfaces::wrap_backend_render_target, vk::{ - Alloc, BackendContext, Format as VkFormat, GetProcOf, ImageInfo as VkImageInfo, - ImageLayout, ImageTiling, + Alloc, + BackendContext, + Format as VkFormat, + GetProcOf, + ImageInfo as VkImageInfo, + ImageLayout, + ImageTiling, }, - BackendRenderTarget, DirectContext, RecordingContext, SurfaceOrigin, + BackendRenderTarget, + DirectContext, + RecordingContext, + SurfaceOrigin, }, gradient_shader::GradientShaderColors, graphics::{ - set_resource_cache_single_allocation_byte_limit, set_resource_cache_total_bytes_limit, + set_resource_cache_single_allocation_byte_limit, + set_resource_cache_total_bytes_limit, }, path::ArcSize, rrect::Corner, @@ -20,14 +38,66 @@ pub use skia_safe::{ surfaces::raster_n32_premul, svg, textlayout::{ - paragraph::GlyphClusterInfo, Decoration, FontCollection, FontFeature, LineMetrics, - Paragraph, ParagraphBuilder, ParagraphStyle, PlaceholderStyle, PositionWithAffinity, - RectHeightStyle, RectWidthStyle, StrutStyle, TextAlign, TextBaseline, TextBox, - TextDecoration, TextDecorationStyle, TextDirection, TextHeightBehavior, TextIndex, - TextRange, TextShadow, TextStyle, TypefaceFontProvider, + paragraph::GlyphClusterInfo, + Decoration, + FontCollection, + FontFeature, + LineMetrics, + Paragraph, + ParagraphBuilder, + ParagraphStyle, + PlaceholderStyle, + PositionWithAffinity, + RectHeightStyle, + RectWidthStyle, + StrutStyle, + TextAlign, + TextBaseline, + TextBox, + TextDecoration, + TextDecorationStyle, + TextDirection, + TextHeightBehavior, + TextIndex, + TextRange, + TextShadow, + TextStyle, + TypefaceFontProvider, }, - Bitmap, BlurStyle, Canvas, ClipOp, Color, ColorSpace, ColorType, Data, EncodedImageFormat, - FilterMode, FontArguments, FontMgr, FontStyle, IPoint, IRect, Image, ImageInfo, MaskFilter, - Matrix, Paint, PaintStyle, Path, PathDirection, Point, RRect, Rect, RuntimeEffect, - SamplingOptions, Shader, Surface, TileMode, Typeface, HSV, M44, RGB, V3, + Bitmap, + BlurStyle, + Canvas, + ClipOp, + Color, + ColorSpace, + ColorType, + Data, + EncodedImageFormat, + FilterMode, + FontArguments, + FontMgr, + FontStyle, + IPoint, + IRect, + Image, + ImageInfo, + MaskFilter, + Matrix, + Paint, + PaintStyle, + Path, + PathDirection, + Point, + RRect, + Rect, + RuntimeEffect, + SamplingOptions, + Shader, + Surface, + TileMode, + Typeface, + HSV, + M44, + RGB, + V3, }; diff --git a/crates/renderer/src/drivers/mod.rs b/crates/renderer/src/drivers/mod.rs index 7bfb214d1..ecd723074 100644 --- a/crates/renderer/src/drivers/mod.rs +++ b/crates/renderer/src/drivers/mod.rs @@ -1,15 +1,17 @@ mod gl; mod vulkan; -pub use gl::*; - use freya_engine::prelude::Surface as SkiaSurface; +pub use gl::*; use glutin::surface::GlSurface; use vulkan::VulkanDriver; use winit::{ dpi::PhysicalSize, event_loop::ActiveEventLoop, - window::{Window, WindowAttributes}, + window::{ + Window, + WindowAttributes, + }, }; use crate::LaunchConfig; diff --git a/crates/renderer/src/drivers/vulkan.rs b/crates/renderer/src/drivers/vulkan.rs index dcc2a473b..05985a8bf 100644 --- a/crates/renderer/src/drivers/vulkan.rs +++ b/crates/renderer/src/drivers/vulkan.rs @@ -1,31 +1,82 @@ -use freya_engine::prelude::{ - backend_render_targets, direct_contexts, wrap_backend_render_target, Alloc, BackendContext, - Canvas, ColorType, DirectContext, GetProcOf, ImageLayout, ImageTiling, Surface as SkiaSurface, - SurfaceOrigin, VkFormat, VkImageInfo, -}; -use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; use std::{ - cell::{Cell, RefCell}, + cell::{ + Cell, + RefCell, + }, sync::Arc, }; + +use freya_engine::prelude::{ + backend_render_targets, + direct_contexts, + wrap_backend_render_target, + Alloc, + BackendContext, + Canvas, + ColorType, + DirectContext, + GetProcOf, + ImageLayout, + ImageTiling, + Surface as SkiaSurface, + SurfaceOrigin, + VkFormat, + VkImageInfo, +}; +use raw_window_handle::{ + HasDisplayHandle, + HasWindowHandle, +}; use vulkano::{ device::{ - physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Queue, - QueueCreateInfo, QueueFlags, + physical::PhysicalDeviceType, + Device, + DeviceCreateInfo, + DeviceExtensions, + Queue, + QueueCreateInfo, + QueueFlags, }, - image::{view::ImageView, Image, ImageUsage}, - instance::{Instance, InstanceCreateFlags, InstanceCreateInfo, InstanceExtensions}, - swapchain::{Surface, Swapchain, SwapchainCreateInfo, SwapchainPresentInfo}, - sync::{self, GpuFuture}, - Handle, Validated, VulkanError, VulkanLibrary, VulkanObject, + image::{ + view::ImageView, + Image, + ImageUsage, + }, + instance::{ + Instance, + InstanceCreateFlags, + InstanceCreateInfo, + InstanceExtensions, + }, + swapchain::{ + Surface, + Swapchain, + SwapchainCreateInfo, + SwapchainPresentInfo, + }, + sync::{ + self, + GpuFuture, + }, + Handle, + Validated, + VulkanError, + VulkanLibrary, + VulkanObject, }; use winit::{ dpi::PhysicalSize, event_loop::ActiveEventLoop, - window::{Window, WindowAttributes}, + window::{ + Window, + WindowAttributes, + }, }; -use crate::{size::WinitSize, LaunchConfig}; +use crate::{ + size::WinitSize, + LaunchConfig, +}; /// Graphics driver using Vulkan. pub struct VulkanDriver { @@ -370,7 +421,10 @@ fn create_surface( }), _, ) => unsafe { - use cocoa::{appkit::NSView, base::id as cocoa_id}; + use cocoa::{ + appkit::NSView, + base::id as cocoa_id, + }; use objc::runtime::YES; let layer = metal::MetalLayer::new(); diff --git a/crates/renderer/src/renderer.rs b/crates/renderer/src/renderer.rs index e2fbad5d9..c45cec97a 100644 --- a/crates/renderer/src/renderer.rs +++ b/crates/renderer/src/renderer.rs @@ -280,8 +280,13 @@ impl<'a, State: Clone> ApplicationHandler for DesktopRenderer<'a, app.measure_layout_on_next_render = false; } + if app.init_accessibility_on_next_render { + app.init_accessibility(window); + app.init_accessibility_on_next_render = false; + } + graphics_driver.make_current(); - + app.render( &self.hovered_node, window_config.background, From 227c5d0a56a270ea1b9e1ce234e3b732235113b6 Mon Sep 17 00:00:00 2001 From: marc2332 Date: Sun, 8 Sep 2024 11:47:32 +0200 Subject: [PATCH 5/6] chore: Add line break --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5219bdd1d..45ae60b19 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,7 +52,7 @@ dioxus-hot-reload = { version = "0.5", features = ["file_watcher"], default-feat dioxus-router = { version = "0.5", default-features = false } dioxus-sdk = { version = "0.5", features = ["clipboard"]} -skia-safe = { version = "0.75.0", features = ["gl", "textlayout", "svg"] } +skia-safe = { version = "0.75.0", features = ["gl", "vulkan", "textlayout", "svg"] } gl = "0.14.0" glutin = "0.32.0" @@ -97,4 +97,4 @@ bytes = "1.5.0" [profile.release] lto = true -opt-level = 3 \ No newline at end of file +opt-level = 3 From 16ecadc9a5469616d1b49b6355df64c7771ad444 Mon Sep 17 00:00:00 2001 From: marc2332 Date: Sun, 8 Sep 2024 12:31:41 +0200 Subject: [PATCH 6/6] chore: Remove canvas clear --- crates/renderer/src/drivers/vulkan.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/renderer/src/drivers/vulkan.rs b/crates/renderer/src/drivers/vulkan.rs index 05985a8bf..cbf40f0d4 100644 --- a/crates/renderer/src/drivers/vulkan.rs +++ b/crates/renderer/src/drivers/vulkan.rs @@ -300,8 +300,6 @@ impl VulkanDriver { ) .expect("Could not create Skia surface"); - skia_surface.canvas().clear(config.window_config.background); - gr_context.flush_and_submit(); let driver = VulkanDriver {