aspen_renderer/window_surface/
mod.rs

1use 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}