Skip to content

Commit 3a67dea

Browse files
authored
chore(skia): improve vulkan backend (#25)
* chore(skia): improve vulkan backend * fix(skia): vulkan backend invalid extent validation error
1 parent a4c2b78 commit 3a67dea

File tree

1 file changed

+65
-38
lines changed

1 file changed

+65
-38
lines changed

crates/anyrender_skia/src/vulkan.rs

Lines changed: 65 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ use skia_safe::{
3333
use std::{
3434
ffi::{CStr, CString},
3535
sync::Arc,
36-
u64,
3736
};
3837

3938
use crate::window_renderer::SkiaBackend;
@@ -53,6 +52,8 @@ pub(crate) struct VulkanBackend {
5352
swapchain_format: Format,
5453
swapchain_extent: Extent2D,
5554
swapchain_image_index: u32,
55+
swapchain_suboptimal: bool,
56+
swapchain_size: (u32, u32),
5657
gr_context: DirectContext,
5758
image_available_semaphore: Semaphore,
5859
render_finished_semaphore: Semaphore,
@@ -88,6 +89,8 @@ impl VulkanBackend {
8889
let (device, queue) = create_logical_device(&instance, physical_device, queue_family_index);
8990
let device = Arc::new(device);
9091

92+
let swapchain_size = (width, height);
93+
9194
let (swapchain, swapchain_fns, swapchain_images, swapchain_format, swapchain_extent) =
9295
create_swapchain(
9396
&instance,
@@ -96,8 +99,7 @@ impl VulkanBackend {
9699
&surface_fns,
97100
surface,
98101
queue_family_index,
99-
width,
100-
height,
102+
swapchain_size,
101103
None,
102104
);
103105

@@ -151,6 +153,8 @@ impl VulkanBackend {
151153
swapchain_format,
152154
swapchain_extent,
153155
swapchain_image_index: 0,
156+
swapchain_suboptimal: false,
157+
swapchain_size,
154158
gr_context,
155159
image_available_semaphore,
156160
render_finished_semaphore,
@@ -159,6 +163,36 @@ impl VulkanBackend {
159163
cmd_buf,
160164
}
161165
}
166+
167+
fn recreate_swapchain(&mut self) {
168+
unsafe {
169+
self.device.device_wait_idle().unwrap();
170+
}
171+
172+
let old_swapchain = self.swapchain;
173+
174+
let (swapchain, swapchain_fns, swapchain_images, swapchain_format, swapchain_extent) =
175+
create_swapchain(
176+
&self.instance,
177+
&self.device,
178+
self.physical_device,
179+
&self.surface_fns,
180+
self.surface,
181+
self.queue_family_index,
182+
self.swapchain_size,
183+
Some(old_swapchain),
184+
);
185+
self.swapchain = swapchain;
186+
self.swapchain_fns = swapchain_fns;
187+
self.swapchain_images = swapchain_images;
188+
self.swapchain_format = swapchain_format;
189+
self.swapchain_extent = swapchain_extent;
190+
self.swapchain_suboptimal = false;
191+
192+
unsafe {
193+
self.swapchain_fns.destroy_swapchain(old_swapchain, None);
194+
}
195+
}
162196
}
163197

164198
impl Drop for VulkanBackend {
@@ -189,31 +223,8 @@ impl Drop for VulkanBackend {
189223

190224
impl SkiaBackend for VulkanBackend {
191225
fn set_size(&mut self, width: u32, height: u32) {
192-
unsafe {
193-
self.device.device_wait_idle().unwrap();
194-
195-
let old_swapchain = self.swapchain;
196-
197-
let (swapchain, swapchain_fns, swapchain_images, swapchain_format, swapchain_extent) =
198-
create_swapchain(
199-
&self.instance,
200-
&self.device,
201-
self.physical_device,
202-
&self.surface_fns,
203-
self.surface,
204-
self.queue_family_index,
205-
width,
206-
height,
207-
Some(old_swapchain),
208-
);
209-
self.swapchain = swapchain;
210-
self.swapchain_fns = swapchain_fns;
211-
self.swapchain_images = swapchain_images;
212-
self.swapchain_format = swapchain_format;
213-
self.swapchain_extent = swapchain_extent;
214-
215-
self.swapchain_fns.destroy_swapchain(old_swapchain, None);
216-
}
226+
self.swapchain_size = (width, height);
227+
self.recreate_swapchain();
217228
}
218229

219230
fn prepare(&mut self) -> Option<Surface> {
@@ -224,7 +235,7 @@ impl SkiaBackend for VulkanBackend {
224235

225236
self.device.reset_fences(&[self.in_flight_fence]).unwrap();
226237

227-
let (image_index, _) = self
238+
let (image_index, suboptimal) = self
228239
.swapchain_fns
229240
.acquire_next_image(
230241
self.swapchain,
@@ -235,6 +246,7 @@ impl SkiaBackend for VulkanBackend {
235246
.unwrap();
236247

237248
self.swapchain_image_index = image_index;
249+
self.swapchain_suboptimal = suboptimal;
238250

239251
let image = self.swapchain_images[image_index as usize];
240252

@@ -334,13 +346,15 @@ impl SkiaBackend for VulkanBackend {
334346
.swapchains(&swapchains)
335347
.image_indices(&image_indices);
336348

337-
unsafe {
338-
self.swapchain_fns
339-
.queue_present(self.queue, &present_info)
340-
.unwrap();
341-
};
349+
let result = unsafe { self.swapchain_fns.queue_present(self.queue, &present_info) };
342350

343351
drop(surface);
352+
353+
if self.swapchain_suboptimal
354+
|| matches!(result, Err(ash::vk::Result::ERROR_OUT_OF_DATE_KHR))
355+
{
356+
self.recreate_swapchain();
357+
}
344358
}
345359
}
346360

@@ -453,8 +467,7 @@ fn create_swapchain(
453467
surface_fns: &InstanceSurfaceFns,
454468
surface: SurfaceKHR,
455469
queue_family_index: u32,
456-
width: u32,
457-
height: u32,
470+
size: (u32, u32),
458471
old_swapchain: Option<SwapchainKHR>,
459472
) -> (
460473
SwapchainKHR,
@@ -494,7 +507,21 @@ fn create_swapchain(
494507
.find(|&m| m == PresentModeKHR::MAILBOX)
495508
.unwrap_or(PresentModeKHR::FIFO);
496509

497-
let extent = Extent2D { width, height };
510+
let extent = if surface_caps.current_extent.width == u32::MAX {
511+
Extent2D {
512+
width: size
513+
.0
514+
.max(surface_caps.min_image_extent.width)
515+
.min(surface_caps.max_image_extent.width),
516+
height: size
517+
.1
518+
.max(surface_caps.min_image_extent.height)
519+
.min(surface_caps.max_image_extent.height),
520+
}
521+
} else {
522+
surface_caps.current_extent
523+
};
524+
498525
let image_count = surface_caps.min_image_count.max(2);
499526

500527
let create_info = SwapchainCreateInfoKHR::default()
@@ -518,7 +545,7 @@ fn create_swapchain(
518545
.clipped(true)
519546
.old_swapchain(old_swapchain.unwrap_or(SwapchainKHR::null()));
520547

521-
let swapchain_fns = DeviceSwapchainFns::new(&instance, &device);
548+
let swapchain_fns = DeviceSwapchainFns::new(instance, device);
522549
let swapchain = unsafe { swapchain_fns.create_swapchain(&create_info, None).unwrap() };
523550
let images = unsafe { swapchain_fns.get_swapchain_images(swapchain).unwrap() };
524551

0 commit comments

Comments
 (0)