Skip to main content

rotex_vulkan/bridge/
surface.rs

1use super::{VulkanBridge, surface_not_attached_error};
2use crate::backend::vulkan::{Device, Semaphore, Swapchain};
3use crate::core::Instance;
4use crate::error::{Error, vk_error};
5use rotex_types::{Extent2D as FrontendExtent2D, SurfaceDescriptor as FrontendSurfaceDescriptor};
6
7impl VulkanBridge {
8    pub fn attach_surface(
9        &mut self,
10        surface_descriptor: FrontendSurfaceDescriptor,
11    ) -> Result<(), Error> {
12        self.destroy_surface_state();
13        let raw_surface = unsafe {
14            ash_window::create_surface(
15                self.instance.raw_entry(),
16                self.instance.raw_instance(),
17                surface_descriptor.display_handle,
18                surface_descriptor.window_handle,
19                None,
20            )
21        }
22        .map_err(vk_error)?;
23        let surface = self.instance.create_surface_from_raw(raw_surface);
24        let extent = super::init::to_vk_extent(surface_descriptor.extent);
25        let swapchain = surface.create_swapchain(&self.instance, &self.device, extent)?;
26        let color_targets =
27            Self::create_targets(self.instance.raw(), self.device.raw(), swapchain.raw(), false)?;
28        let image_available = Semaphore::new(self.device.raw())?;
29        let render_finished =
30            Self::create_render_finished(self.device.raw(), swapchain.raw().images().len())?;
31        self.surface_state = Some(super::types::SurfaceState {
32            surface,
33            swapchain,
34            extent,
35            color_targets,
36            depth_targets: None,
37            image_available,
38            render_finished,
39        });
40        Ok(())
41    }
42
43    pub(super) fn create_targets(
44        instance: &Instance,
45        device: &Device,
46        swapchain: &Swapchain,
47        with_depth: bool,
48    ) -> Result<super::types::RenderTargets, Error> {
49        let depth_format = if with_depth {
50            Some(super::render::find_depth_format(instance, device)?)
51        } else {
52            None
53        };
54        let render_pass = super::render::create_render_pass(device, swapchain.format(), depth_format)?;
55        let depth_image = match depth_format {
56            Some(format) => Some(super::render::create_depth_image(
57                instance,
58                device,
59                swapchain.extent(),
60                format,
61            )?),
62            None => None,
63        };
64        let framebuffers = super::render::build_framebuffers(
65            device,
66            swapchain,
67            render_pass.handle(),
68            depth_image.as_ref(),
69        )?;
70        Ok(super::types::RenderTargets {
71            render_pass,
72            framebuffers,
73            depth_image,
74        })
75    }
76
77    pub(super) fn recreate_swapchain(&mut self) -> Result<(), Error> {
78        unsafe { self.device.raw().logical_device().device_wait_idle() }.map_err(vk_error)?;
79        self.destroy_all_pipelines();
80        let Some(state) = self.surface_state.as_mut() else {
81            return Err(surface_not_attached_error());
82        };
83        for sem in state.render_finished.drain(..) {
84            sem.destroy(self.device.raw());
85        }
86        let old_swapchain_handle = state.swapchain.handle();
87        let mut old_swapchain = std::mem::replace(
88            &mut state.swapchain,
89            state.surface.create_swapchain_with_old(
90                &self.instance,
91                &self.device,
92                state.extent,
93                old_swapchain_handle,
94            )?,
95        );
96        old_swapchain.destroy_in_place(&self.device);
97
98        let old_color_targets = std::mem::replace(
99            &mut state.color_targets,
100            Self::create_targets(
101                self.instance.raw(),
102                self.device.raw(),
103                state.swapchain.raw(),
104                false,
105            )?,
106        );
107        old_color_targets.destroy(self.device.raw());
108
109        if let Some(old_depth_targets) = state.depth_targets.take() {
110            old_depth_targets.destroy(self.device.raw());
111            state.depth_targets = Some(Self::create_targets(
112                self.instance.raw(),
113                self.device.raw(),
114                state.swapchain.raw(),
115                true,
116            )?);
117        }
118
119        state.render_finished =
120            Self::create_render_finished(self.device.raw(), state.swapchain.raw().images().len())?;
121        Ok(())
122    }
123
124    pub(super) fn ensure_depth_targets(&mut self) -> Result<(), Error> {
125        let Some(state) = self.surface_state.as_mut() else {
126            return Err(surface_not_attached_error());
127        };
128        if state.depth_targets.is_none() {
129            state.depth_targets = Some(Self::create_targets(
130                self.instance.raw(),
131                self.device.raw(),
132                state.swapchain.raw(),
133                true,
134            )?);
135        }
136        Ok(())
137    }
138
139    pub(super) fn create_render_finished(
140        device: &Device,
141        count: usize,
142    ) -> Result<Vec<Semaphore>, Error> {
143        (0..count).map(|_| Semaphore::new(device)).collect()
144    }
145
146    pub fn resize(&mut self, extent: FrontendExtent2D) -> Result<(), Error> {
147        if let Some(state) = self.surface_state.as_mut() {
148            state.extent = super::init::to_vk_extent(extent);
149            return self.recreate_swapchain();
150        }
151        Err(surface_not_attached_error())
152    }
153
154    pub fn destroy(mut self) {
155        let _ = self.in_flight_fence.wait(self.device.raw(), u64::MAX);
156        unsafe {
157            let _ = self.device.raw().logical_device().device_wait_idle();
158        }
159        self.destroy_all_pipelines();
160        for (_, mesh) in self.meshes.drain() {
161            mesh.vertex_buffer.destroy(self.device.raw());
162            mesh.index_buffer.destroy(self.device.raw());
163        }
164        for (_, texture) in self.textures.drain() {
165            texture.destroy(self.device.raw(), &self.texture_descriptor_pool);
166        }
167        if let Some(default_texture) = self.default_texture.take() {
168            default_texture.destroy(self.device.raw(), &self.texture_descriptor_pool);
169        }
170        self.destroy_surface_state();
171        self.texture_descriptor_pool.destroy(self.device.raw());
172        self.texture_set_layout.destroy(self.device.raw());
173        self.command_pool.destroy(self.device.raw());
174        self.in_flight_fence.destroy(self.device.raw());
175        self.device.destroy();
176        self.instance.destroy();
177    }
178
179    pub(super) fn destroy_surface_state(&mut self) {
180        if let Some(state) = self.surface_state.take() {
181            for sem in state.render_finished {
182                sem.destroy(self.device.raw());
183            }
184            state.image_available.destroy(self.device.raw());
185            state.color_targets.destroy(self.device.raw());
186            if let Some(depth_targets) = state.depth_targets {
187                depth_targets.destroy(self.device.raw());
188            }
189            state.swapchain.destroy(&self.device);
190            state.surface.destroy();
191        }
192    }
193}