aspen_renderer/window_surface/
mod.rs1use std::sync::Arc;
2
3use vulkano::{
4 device::Device, image::{view::ImageView, Image, ImageUsage}, pipeline::graphics::viewport::Viewport, render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass}, swapchain::{Surface, Swapchain, SwapchainCreateInfo}, sync::{future::FenceSignalFuture, GpuFuture}
5};
6use winit::{dpi::PhysicalSize, event_loop::EventLoop, window::{Window, WindowBuilder}};
7
8pub struct WindowSurface {
9 pub window: Arc<Window>,
10 pub swapchain: Arc<Swapchain>,
11 pub images: Vec<Arc<Image>>,
12 pub framebuffers: Vec<Arc<Framebuffer>>,
13 pub renderpass: Arc<RenderPass>,
14 pub viewport: Viewport,
15 pub recreate_swapchain: bool,
16 pub previous_frame_fences: Vec<Option<Arc<FenceSignalFuture<Box<dyn GpuFuture + Send>>>>>,
17 pub previous_frame_index: u32,
18}
19
20impl WindowSurface {
21 pub fn new<ELT>(event_loop: &EventLoop<ELT>, device: Arc<Device>) -> Self {
22 let window = WindowBuilder::new()
23 .with_title("New window")
24 .with_inner_size(PhysicalSize::new(400, 400))
25 .build(event_loop)
26 .unwrap();
27
28 let window = Arc::new(window);
29
30 let surface = Surface::from_window(device.instance().clone(), window.clone()).unwrap();
31
32 let (swapchain, images) = {
33 let surface_capabilities = device
34 .physical_device()
35 .surface_capabilities(&surface, Default::default())
36 .unwrap();
37
38 let image_format = device
39 .physical_device()
40 .surface_formats(&surface, Default::default())
41 .unwrap()[0]
42 .0;
43
44 Swapchain::new(
45 device.clone(),
46 surface,
47 SwapchainCreateInfo {
48 min_image_count: surface_capabilities.min_image_count.max(2),
49 image_format,
50 image_extent: window.inner_size().into(),
51 image_usage: ImageUsage::COLOR_ATTACHMENT,
52 composite_alpha: surface_capabilities
53 .supported_composite_alpha
54 .into_iter()
55 .next()
56 .unwrap(),
57 present_mode: vulkano::swapchain::PresentMode::Fifo,
58 ..Default::default()
59 },
60 ).unwrap()
61 };
62
63 let viewport = Viewport {
64 offset: [0.0, 0.0],
65 extent: [0.0, 0.0],
66 depth_range: 0.0..=1.0,
67 };
68
69 let previous_frame_fences = (0..images.len())
70 .map(|_| { None })
71 .collect::<Vec<_>>();
72
73 let renderpass = vulkano::single_pass_renderpass!(
74 device.clone(),
75 attachments: {
76 color: {
77 format: swapchain.image_format(),
78 samples: 1,
79 load_op: Clear,
80 store_op: Store,
81 },
82 },
83 pass: {
84 color: [color],
85 depth_stencil: {},
86 },
87 )
88 .unwrap();
89
90 let mut s = Self {
91 window,
92 swapchain,
93 images,
94 framebuffers: Vec::new(),
95 renderpass: renderpass.clone(),
96 previous_frame_fences,
97 viewport,
98 recreate_swapchain: true,
99 previous_frame_index: 0
100 };
101
102 s.image_size_dependent_setup(renderpass.clone());
103
104 s
105 }
106
107 pub fn image_size_dependent_setup(&mut self, render_pass: Arc<RenderPass>) {
108 let extent = self.images[0].extent();
109 self.viewport.extent = [extent[0] as f32, extent[1] as f32];
110
111 self.framebuffers = self.images
112 .iter()
113 .map(|image| {
114 let view = ImageView::new_default(image.clone()).unwrap();
115 Framebuffer::new(
116 render_pass.clone(),
117 FramebufferCreateInfo {
118 attachments: vec![view],
119 ..Default::default()
120 },
121 )
122 .unwrap()
123 })
124 .collect::<Vec<_>>()
125 }
126}