rotex_vulkan/bridge/
surface.rs1use 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}