narui_core/vulkano_render/
render.rs1use super::{glyph_brush::GlyphBrush, input_handler::InputHandler, lyon::Lyon};
2use crate::{
3 eval::{
4 delta_eval::Evaluator,
5 layout::{Layouter, PositionedElement},
6 },
7 geom::Rect,
8 util::fps_report::FPSReporter,
9 RenderObject,
10 UnevaluatedFragment,
11};
12use freelist::Idx;
13
14use crate::{
15 context::context,
16 eval::layout::RenderObjectOrSubPass,
17 vulkano_render::{
18 primitive_renderer::Renderer,
19 subpass_stack::{create_framebuffer, AbstractFramebuffer, AbstractImage, SubPassStack},
20 vk_util::VulkanContext,
21 },
22};
23use std::{
24 sync::Arc,
25 time::{Duration, Instant},
26};
27use vulkano::{
28 format::Format,
29 image::{ImageAccess, ImageUsage, SwapchainImage},
30 render_pass::RenderPass,
31 swapchain,
32 swapchain::{AcquireError, PresentMode, Swapchain, SwapchainCreationError},
33 sync,
34 sync::{FlushError, GpuFuture},
35};
36use vulkano_win::VkSurfaceBuild;
37use winit::{
38 event::{Event, WindowEvent},
39 event_loop::{ControlFlow, EventLoop},
40 platform::run_return::EventLoopExtRunReturn,
41 window::{Window, WindowBuilder},
42};
43
44pub fn render(window_builder: WindowBuilder, top_node: UnevaluatedFragment) {
45 let mut event_loop: EventLoop<()> = EventLoop::new();
46 let VulkanContext { device, queues } = VulkanContext::create().unwrap();
47 let surface = window_builder.build_vk_surface(&event_loop, device.instance().clone()).unwrap();
48 let queue = queues
49 .iter()
50 .find(|&q| {
51 q.family().supports_graphics() && surface.is_supported(q.family()).unwrap_or(false)
52 })
53 .unwrap()
54 .clone();
55
56 let mut dimensions;
57
58 let caps = surface.capabilities(device.physical_device()).unwrap();
59 let format = Format::B8G8R8A8_SRGB;
60 let (mut swapchain, images) = {
61 let alpha = caps.supported_composite_alpha.iter().next().unwrap();
62 dimensions = surface.window().inner_size().into();
63 Swapchain::start(device.clone(), surface.clone())
64 .usage(ImageUsage {
65 color_attachment: true,
66 transfer_destination: true,
67 ..ImageUsage::none()
68 })
69 .num_images(caps.min_image_count)
70 .composite_alpha(alpha)
71 .dimensions(dimensions)
72 .present_mode(
73 if std::env::var("NARUI_PRESENT_MODE_MAILBOX").is_ok() {
74 PresentMode::Mailbox
75 } else {
76 PresentMode::Fifo
77 },
78 )
79 .format(format)
80 .build()
81 .expect("cant create swapchain")
82 };
83
84 let render_pass = vulkano::single_pass_renderpass!(device.clone(),
85 attachments: {
86 intermediary: {
87 load: Load,
88 store: Store,
89 format: swapchain.format(),
90 samples: 4,
91 },
92 depth: {
93 load: Load,
94 store: Store,
95 format: Format::D16_UNORM,
96 samples: 4,
97 },
98 color: {
99 load: DontCare,
100 store: Store,
101 format: swapchain.format(),
102 samples: 1,
103 }
104 },
105 pass: {
106 color: [intermediary],
107 depth_stencil: {depth},
108 resolve: [color],
109 }
110 )
111 .unwrap();
112
113 let mut framebuffers = window_size_dependent_setup(&images, render_pass.clone());
114 let mut previous_frame_end = Some(sync::now(device.clone()).boxed());
115
116
117 let mut fps_report = FPSReporter::new("gui");
118
119 let mut lyon_renderer = Lyon::new();
120 let mut text_render = GlyphBrush::new(queue.clone());
121 let mut renderer = Renderer::new(render_pass.clone(), device.clone(), queue.clone());
122 let mut input_handler = InputHandler::new();
123
124 let mut layouter = Layouter::new();
125 let mut evaluator = Evaluator::new(
126 context::VulkanContext { device: device.clone(), queues, render_pass: render_pass.clone() },
127 top_node,
128 &mut layouter,
129 );
130
131 let mut recreate_swapchain = false;
132 let mut has_update = true;
133 let mut input_render_objects: Vec<(Idx, Option<Rect>)> = Vec::new();
134
135 event_loop.run_return(move |event, _, control_flow| {
136 *control_flow = ControlFlow::WaitUntil(Instant::now() + Duration::from_millis(1000 / 70));
137 match event {
138 Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => {
139 *control_flow = ControlFlow::Exit;
140 }
141 Event::WindowEvent { event: WindowEvent::Resized(_), .. } => {
142 recreate_swapchain = true;
143 surface.window().request_redraw();
144 }
145 Event::WindowEvent { event, .. } => {
146 input_handler.enqueue_input(event);
147 *control_flow = ControlFlow::Poll;
148 return;
149 }
150 Event::MainEventsCleared => {
151 input_handler.handle_input(
152 &input_render_objects[..],
153 &layouter,
154 evaluator.callback_context(&layouter),
155 );
156 has_update |= evaluator.update(&mut layouter);
157 if has_update {
158 surface.window().request_redraw();
159 }
160 }
161 Event::RedrawRequested(_) => {
162 previous_frame_end.as_mut().unwrap().cleanup_finished();
163
164 if recreate_swapchain {
165 dimensions = surface.window().inner_size().into();
166 let (new_swapchain, new_images) =
167 match swapchain.recreate().dimensions(dimensions).build() {
168 Ok(r) => r,
169 Err(SwapchainCreationError::UnsupportedDimensions) => {
170 return;
171 }
172 Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
173 };
174
175 swapchain = new_swapchain;
176 framebuffers = window_size_dependent_setup(&new_images, render_pass.clone());
177 recreate_swapchain = false;
178 }
179
180 let (image_num, acquire_fut) = match swapchain::acquire_next_image(
181 swapchain.clone(),
182 Some(Duration::from_millis(0)),
183 ) {
184 Ok((image_num, suboptimal, acquire_future)) => {
185 if suboptimal {
186 println!("swapchain suboptimal, need to recreate it");
187 recreate_swapchain = true;
188 }
189 (image_num, acquire_future)
190 }
191 Err(AcquireError::OutOfDate) => {
192 println!("swapchain suboptimal, need to recreate it");
193 recreate_swapchain = true;
194 return;
195 }
196 Err(e) => panic!("Failed to acquire next image: {:?}", e),
197 };
198
199 has_update = false;
200
201 let (framebuffer, intermediary_image, depth_image): &(
202 AbstractFramebuffer,
203 AbstractImage,
204 AbstractImage,
205 ) = &framebuffers[image_num];
206
207 input_render_objects.clear();
208
209 layouter.do_layout(evaluator.top_node, dimensions.into());
210
211 let mut subpass_stack = SubPassStack::new(
212 format,
213 queue.clone(),
214 render_pass.clone(),
215 framebuffer.clone(),
216 intermediary_image.clone(),
217 depth_image.clone(),
218 );
219
220 for (_, obj) in layouter.iter_layouted(evaluator.top_node) {
221 text_render.prerender(&obj);
222 }
223 let (mut text_state, texture, texture_fut) = text_render.finish(&mut renderer.data);
224
225 for (idx, obj) in layouter.iter_layouted(evaluator.top_node) {
226 subpass_stack.handle(&renderer.data, &obj);
227 lyon_renderer.render(&mut renderer.data, &obj);
228 text_render.render(&obj, &mut renderer.data, &mut text_state);
229 renderer.render(&obj);
230 if let PositionedElement {
231 element: RenderObjectOrSubPass::RenderObject(RenderObject::Input { .. }),
232 ..
233 } = &obj
234 {
235 input_render_objects.push((idx, obj.clipping_rect));
236 }
237 }
238 subpass_stack.finish(&renderer.data);
239 let (
240 vertex_fut,
241 primitive_fut,
242 index_fut,
243 descriptor_set,
244 vertex_buffer,
245 index_buffer,
246 ) = renderer.finish(texture);
247
248 let after_frame_callbacks = std::mem::take(&mut evaluator.after_frame_callbacks);
249 let callback_context = evaluator.callback_context(&layouter);
250 let command_buffer = subpass_stack.render(
251 &callback_context,
252 |builder, viewport, dimensions, offset, start, end| {
253 renderer.render_part(
254 builder,
255 descriptor_set.clone(),
256 viewport,
257 dimensions,
258 offset,
259 start,
260 end,
261 )
262 },
263 vertex_buffer,
264 index_buffer,
265 );
266 fps_report.frame();
267
268 let future = previous_frame_end
269 .take()
270 .unwrap()
271 .join(
272 texture_fut
273 .map(|v| Box::new(v) as Box<dyn GpuFuture>)
274 .unwrap_or_else(|| Box::new(sync::now(device.clone())) as _),
275 )
276 .join(index_fut)
277 .join(vertex_fut)
278 .join(primitive_fut)
279 .join(acquire_fut)
280 .then_execute(queue.clone(), command_buffer)
281 .unwrap()
282 .then_swapchain_present(queue.clone(), swapchain.clone(), image_num)
283 .then_signal_fence_and_flush();
284
285 match future {
286 Ok(future) => {
287 previous_frame_end = Some(future.boxed());
288 }
289 Err(FlushError::OutOfDate) => {
290 recreate_swapchain = true;
291 previous_frame_end = Some(sync::now(device.clone()).boxed());
292 }
293 Err(e) => {
294 println!("Failed to flush future: {:?}", e);
295 previous_frame_end = Some(sync::now(device.clone()).boxed());
296 }
297 }
298
299 for callback in after_frame_callbacks {
300 callback(&callback_context);
301 }
302 }
303 _e => {}
304 }
305 });
306}
307
308fn window_size_dependent_setup(
311 images: &[Arc<SwapchainImage<Window>>],
312 render_pass: Arc<RenderPass>,
313) -> Vec<(AbstractFramebuffer, AbstractImage, AbstractImage)> {
314 let dimensions = images[0].dimensions();
315 images
316 .iter()
317 .map(|image| {
318 let fb = create_framebuffer(
319 [dimensions.width(), dimensions.height()],
320 render_pass.clone(),
321 image.format(),
322 Some(image.clone()),
323 );
324 (fb.0, fb.3, fb.4)
325 })
326 .collect::<Vec<_>>()
327}