1pub mod window_surface;
2pub mod drawable;
3pub mod renderpass;
4pub mod submit_system;
5pub mod render_system;
6
7use std::{
8 collections::HashMap,
9 sync::{
10 mpsc::{
11 sync_channel,
12 channel,
13 Receiver,
14 Sender,
15 SyncSender
16 },
17 Arc,
18 Mutex
19 },
20 thread
21};
22
23use render_system::RenderSystem;
24use vulkano::{
25 command_buffer::allocator::StandardCommandBufferAllocator,
26 descriptor_set::allocator::StandardDescriptorSetAllocator,
27 device::{
28 physical::PhysicalDeviceType,
29 Device,
30 DeviceCreateInfo,
31 DeviceExtensions,
32 Features,
33 Queue,
34 QueueCreateInfo,
35 QueueFlags
36 },
37 image::{
38 view::ImageView,
39 Image,
40 ImageUsage
41 },
42 instance::{
43 Instance,
44 InstanceCreateFlags,
45 InstanceCreateInfo
46 },
47 memory::allocator::StandardMemoryAllocator,
48 pipeline::graphics::viewport::Viewport,
49 render_pass::{
50 Framebuffer,
51 FramebufferCreateInfo,
52 RenderPass
53 },
54 swapchain::{
55 Surface,
56 Swapchain,
57 SwapchainCreateInfo
58 },
59 VulkanLibrary
60};
61
62use window_surface::WindowSurface;
63use winit::{
64 dpi::PhysicalSize, event_loop::EventLoop, window::{WindowBuilder, WindowId}
65};
66
67#[derive(Clone)]
68pub struct GraphicsObjects {
69 pub device: Arc<Device>,
70 pub graphics_queue: Arc<Queue>,
71 pub descriptor_set_allocator: Arc<StandardDescriptorSetAllocator>,
72 pub command_buffer_allocator: Arc<StandardCommandBufferAllocator>,
73 pub memory_allocator: Arc<StandardMemoryAllocator>
74}
75
76pub struct Renderer {
77 pub comms: RenderThreadComms,
78 pub windows: HashMap<WindowId, Arc<Mutex<WindowSurface>>>,
79 pub graphics_objects: GraphicsObjects,
80}
81
82impl Renderer {
83 pub fn new<ELT>(event_loop: &EventLoop<ELT>) -> (Self, WindowId) {
84 let library = VulkanLibrary::new().unwrap();
85 let required_extensions = Surface::required_extensions(&event_loop);
86
87 let instance = Instance::new(
88 library,
89 InstanceCreateInfo {
90 flags: InstanceCreateFlags::ENUMERATE_PORTABILITY,
91 enabled_extensions: required_extensions,
92 ..Default::default()
93 },
94 ).unwrap();
95
96 let window = Arc::new(
97 WindowBuilder::new()
98 .with_title("Primary window")
99 .with_inner_size(PhysicalSize::new(400, 400))
100 .build(&event_loop)
101 .unwrap()
102 );
103 let surface = Surface::from_window(instance.clone(), window.clone()).unwrap();
104
105 let device_extensions = DeviceExtensions {
106 khr_swapchain: true,
107 ..DeviceExtensions::empty()
108 };
109
110 let (physical_device, queue_family_index) = instance
111 .enumerate_physical_devices()
112 .unwrap()
113 .filter(|p| {
114 p.supported_extensions().contains(&device_extensions)
115 })
116 .filter_map(|p| {
117 p.queue_family_properties()
118 .iter()
119 .enumerate()
120 .position(|(i, q)| {
121 q.queue_flags.intersects(QueueFlags::GRAPHICS)
122 && p.surface_support(i as u32, &surface).unwrap_or(false)
123 })
124 .map(|i| (p, i as u32))
125 })
126 .min_by_key(|(p, _)| {
127 match p.properties().device_type {
128 PhysicalDeviceType::DiscreteGpu => 0,
129 PhysicalDeviceType::IntegratedGpu => 1,
130 PhysicalDeviceType::VirtualGpu => 2,
131 PhysicalDeviceType::Cpu => 3,
132 PhysicalDeviceType::Other => 4,
133 _ => 5,
134 }
135 })
136 .expect("no suitable physical device found");
137
138
139 println!(
140 "Using device: {} (type: {:?})\nVulkan version: {}\nCompute subgroup size: {}\nVertex buffer binding limit: {}",
141 physical_device.properties().device_name,
142 physical_device.properties().device_type,
143 physical_device.api_version(),
144 physical_device.properties().subgroup_size.unwrap(),
145 physical_device.properties().max_vertex_input_bindings,
146 );
147
148 let (device, mut queues) = Device::new(
149 physical_device,
150 DeviceCreateInfo {
151 enabled_extensions: device_extensions,
152 enabled_features: Features {
153 ..Default::default()
154 },
155 queue_create_infos: vec![QueueCreateInfo {
156 queue_family_index,
157 ..Default::default()
158 }],
159
160 ..Default::default()
161 },
162 ).unwrap();
163
164 let queue = queues.next().unwrap();
165
166 let (swapchain, images) = {
167 let surface_capabilities = device
168 .physical_device()
169 .surface_capabilities(&surface, Default::default())
170 .unwrap();
171
172 let image_format = device
173 .physical_device()
174 .surface_formats(&surface, Default::default())
175 .unwrap()[0]
176 .0;
177
178 Swapchain::new(
179 device.clone(),
180 surface,
181 SwapchainCreateInfo {
182 min_image_count: surface_capabilities.min_image_count.max(2),
183 image_format,
184 image_extent: window.inner_size().into(),
185 image_usage: ImageUsage::COLOR_ATTACHMENT,
186 composite_alpha: surface_capabilities
187 .supported_composite_alpha
188 .into_iter()
189 .next()
190 .unwrap(),
191 present_mode: vulkano::swapchain::PresentMode::Fifo,
192 ..Default::default()
193 },
194 ).unwrap()
195 };
196
197 let renderpass = vulkano::single_pass_renderpass!(
198 device.clone(),
199 attachments: {
200 color: {
201 format: swapchain.image_format(),
202 samples: 1,
203 load_op: Clear,
204 store_op: Store,
205 },
206 },
207 pass: {
208 color: [color],
209 depth_stencil: {},
210 },
211 )
212 .unwrap();
213
214 let memory_allocator = Arc::new(StandardMemoryAllocator::new_default(device.clone()));
215
216 let descriptor_set_allocator = Arc::new(StandardDescriptorSetAllocator::new(
217 device.clone(),
218 Default::default()
219 ));
220
221 let mut viewport = Viewport {
222 offset: [0.0, 0.0],
223 extent: [0.0, 0.0],
224 depth_range: 0.0..=1.0,
225 };
226
227 let framebuffers = window_size_dependent_setup(&images, renderpass.clone(), &mut viewport);
228 let previous_frame_fences = (0..images.len())
229 .map(|_| { None })
230 .collect::<Vec<_>>();
231
232 let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
233 device.clone(),
234 Default::default(),
235 ));
236
237 let mut windows = HashMap::new();
238 let window_id = window.id();
239 windows.insert(
240 window_id,
241 Arc::new(
242 Mutex::new(
243 WindowSurface {
244 window,
245 swapchain,
246 images,
247 framebuffers,
248 renderpass: renderpass.clone(),
249 viewport,
250 recreate_swapchain: true,
251 previous_frame_fences,
252 previous_frame_index: 0
253 }
254 )
255 )
256 );
257
258 let graphics_objects_original = GraphicsObjects {
262 device: device.clone(),
263 graphics_queue: queue.clone(),
264 descriptor_set_allocator: descriptor_set_allocator.clone(),
265 command_buffer_allocator: command_buffer_allocator.clone(),
266 memory_allocator: memory_allocator.clone(),
267 };
268
269 let graphics_objects = graphics_objects_original.clone();
270
271 let (sender, reciever) = sync_channel::<(Box<dyn RenderSystem + Send>, Sender<()>)>(1);
272 let render_closure = move || {
273 let graphics_objects = Arc::new(graphics_objects_original.clone());
274 loop {
275 match reciever.recv() {
276 Err(_) => break,
277 Ok((mut rendergraph, msender)) => {
278 rendergraph.run(graphics_objects.clone());
279
280 _ = msender.send(())
281 },
282 }
283 }
284 };
285
286 let render_thread = thread::Builder::new()
287 .name("main_render_thread".to_string())
288 .spawn(render_closure)
289 .expect("failed to spawn main render thread");
290
291 let comms = RenderThreadComms {
292 sender: Some(sender),
293 render_thread: Some(render_thread)
294 };
295
296 (
297 Self {
298 comms,
299 windows,
300 graphics_objects
301 },
302 window_id
303 )
304 }
305
306 pub fn device(&self) -> &Arc<Device> {
307 &self.graphics_objects.device
308 }
309
310 pub fn allocator(&self) -> &Arc<StandardMemoryAllocator> {
311 &self.graphics_objects.memory_allocator
312 }
313}
314
315pub struct RenderThreadComms {
316 pub sender: Option<SyncSender<(Box<dyn RenderSystem + Send>, Sender<()>)>>,
317 pub render_thread: Option<thread::JoinHandle<()>>,
318}
319
320impl RenderThreadComms {
321 pub fn send(&mut self, render_system: Box<dyn RenderSystem + Send>) -> PresentBarrier {
322 let (sender, reciever) = channel();
323 self.sender.as_ref().unwrap().send((render_system, sender)).expect("Render thread hung up");
324 PresentBarrier {
325 reciever: Some(reciever)
326 }
327 }
328}
329
330impl Drop for RenderThreadComms {
331 fn drop(&mut self) {
332 _ = self.sender.take();
333 _ = self.render_thread.take().unwrap().join();
334 }
335}
336
337pub struct PresentBarrier {
338 reciever: Option<Receiver<()>>
339}
340
341impl PresentBarrier {
342 pub fn blocking_wait(&mut self) {
343 if let Some(reciever) = self.reciever.as_ref() {
344 _ = reciever.recv();
345 self.reciever = None
346 }
347 }
348}
349
350impl Drop for PresentBarrier {
351 fn drop(&mut self) {
352 self.blocking_wait()
353 }
354}
355
356fn window_size_dependent_setup(
357 images: &[Arc<Image>],
358 render_pass: Arc<RenderPass>,
359 viewport: &mut Viewport,
360) -> Vec<Arc<Framebuffer>> {
361 let extent = images[0].extent();
362 viewport.extent = [extent[0] as f32, extent[1] as f32];
363
364 images
365 .iter()
366 .map(|image| {
367 let view = ImageView::new_default(image.clone()).unwrap();
368 Framebuffer::new(
369 render_pass.clone(),
370 FramebufferCreateInfo {
371 attachments: vec![view],
372 ..Default::default()
373 },
374 )
375 .unwrap()
376 })
377 .collect::<Vec<_>>()
378}