1use ash::{vk, Device};
2use bytemuck::bytes_of;
3use egui_winit::winit;
4use std::fmt::Debug;
5use std::{
6 collections::HashMap,
7 ffi::CString,
8 fmt::Formatter,
9 sync::{
10 atomic::{AtomicU64, Ordering},
11 mpsc::{self, Receiver, Sender},
12 Arc, Mutex,
13 },
14};
15
16use crate::allocator::{Allocation, AllocationCreateInfo, Allocator, MemoryLocation};
17use crate::utils;
18
19struct ViewportRendererState<A: Allocator + 'static> {
20 width: u32,
21 height: u32,
22 render_pass: vk::RenderPass,
23 pipeline_layout: vk::PipelineLayout,
24 pipeline: vk::Pipeline,
25 swapchain_image_views: Vec<vk::ImageView>,
26 framebuffers: Vec<vk::Framebuffer>,
27 vertex_buffers: Vec<vk::Buffer>,
28 vertex_buffer_allocations: Vec<A::Allocation>,
29 index_buffers: Vec<vk::Buffer>,
30 index_buffer_allocations: Vec<A::Allocation>,
31 scale_factor: f32,
32 physical_width: u32,
33 physical_height: u32,
34}
35
36#[derive(Clone)]
37struct ViewportRenderer<A: Allocator + 'static> {
38 device: Device,
39 descriptor_set_layout: vk::DescriptorSetLayout,
40 allocator: A,
41 state: Arc<Mutex<Option<ViewportRendererState<A>>>>,
42}
43impl<A: Allocator + 'static> ViewportRenderer<A> {
44 fn new(device: Device, descriptor_set_layout: vk::DescriptorSetLayout, allocator: A) -> Self {
45 Self {
46 device,
47 descriptor_set_layout,
48 allocator,
49 state: Arc::new(Mutex::new(None)),
50 }
51 }
52
53 fn create_render_pass(device: &Device, surface_format: vk::Format) -> vk::RenderPass {
54 unsafe {
55 device.create_render_pass(
56 &vk::RenderPassCreateInfo::builder()
57 .attachments(std::slice::from_ref(
58 &vk::AttachmentDescription::builder()
59 .format(surface_format)
60 .samples(vk::SampleCountFlags::TYPE_1)
61 .load_op(vk::AttachmentLoadOp::LOAD)
62 .store_op(vk::AttachmentStoreOp::STORE)
63 .stencil_load_op(vk::AttachmentLoadOp::DONT_CARE)
64 .stencil_store_op(vk::AttachmentStoreOp::DONT_CARE)
65 .initial_layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
66 .final_layout(vk::ImageLayout::PRESENT_SRC_KHR),
67 ))
68 .subpasses(std::slice::from_ref(
69 &vk::SubpassDescription::builder()
70 .pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS)
71 .color_attachments(std::slice::from_ref(
72 &vk::AttachmentReference::builder()
73 .attachment(0)
74 .layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL),
75 )),
76 ))
77 .dependencies(std::slice::from_ref(
78 &vk::SubpassDependency::builder()
79 .src_subpass(vk::SUBPASS_EXTERNAL)
80 .dst_subpass(0)
81 .src_access_mask(vk::AccessFlags::COLOR_ATTACHMENT_WRITE)
82 .dst_access_mask(vk::AccessFlags::COLOR_ATTACHMENT_WRITE)
83 .src_stage_mask(vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT)
84 .dst_stage_mask(vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT),
85 )),
86 None,
87 )
88 }
89 .expect("Failed to create render pass.")
90 }
91
92 fn create_pipeline_layout(
93 device: &Device,
94 descriptor_set_layout: vk::DescriptorSetLayout,
95 ) -> vk::PipelineLayout {
96 unsafe {
97 device.create_pipeline_layout(
98 &vk::PipelineLayoutCreateInfo::builder()
99 .set_layouts(&[descriptor_set_layout])
100 .push_constant_ranges(std::slice::from_ref(
101 &vk::PushConstantRange::builder()
102 .stage_flags(vk::ShaderStageFlags::VERTEX)
103 .offset(0)
104 .size(std::mem::size_of::<f32>() as u32 * 2),
105 )),
106 None,
107 )
108 }
109 .expect("Failed to create pipeline layout.")
110 }
111
112 fn create_pipeline(
113 device: &Device,
114 render_pass: vk::RenderPass,
115 pipeline_layout: vk::PipelineLayout,
116 ) -> vk::Pipeline {
117 let attributes = [
118 vk::VertexInputAttributeDescription::builder()
120 .binding(0)
121 .offset(0)
122 .location(0)
123 .format(vk::Format::R32G32_SFLOAT)
124 .build(),
125 vk::VertexInputAttributeDescription::builder()
127 .binding(0)
128 .offset(8)
129 .location(1)
130 .format(vk::Format::R32G32_SFLOAT)
131 .build(),
132 vk::VertexInputAttributeDescription::builder()
134 .binding(0)
135 .offset(16)
136 .location(2)
137 .format(vk::Format::R8G8B8A8_UNORM)
138 .build(),
139 ];
140
141 let vertex_shader_module = {
142 let bytes_code = include_bytes!("shaders/spv/vert.spv");
143 let shader_module_create_info = vk::ShaderModuleCreateInfo {
144 code_size: bytes_code.len(),
145 p_code: bytes_code.as_ptr() as *const u32,
146 ..Default::default()
147 };
148 unsafe { device.create_shader_module(&shader_module_create_info, None) }
149 .expect("Failed to create vertex shader module.")
150 };
151 let fragment_shader_module = {
152 let bytes_code = include_bytes!("shaders/spv/frag.spv");
153 let shader_module_create_info = vk::ShaderModuleCreateInfo {
154 code_size: bytes_code.len(),
155 p_code: bytes_code.as_ptr() as *const u32,
156 ..Default::default()
157 };
158 unsafe { device.create_shader_module(&shader_module_create_info, None) }
159 .expect("Failed to create fragment shader module.")
160 };
161 let main_function_name = CString::new("main").unwrap();
162 let pipeline_shader_stages = [
163 vk::PipelineShaderStageCreateInfo::builder()
164 .stage(vk::ShaderStageFlags::VERTEX)
165 .module(vertex_shader_module)
166 .name(&main_function_name)
167 .build(),
168 vk::PipelineShaderStageCreateInfo::builder()
169 .stage(vk::ShaderStageFlags::FRAGMENT)
170 .module(fragment_shader_module)
171 .name(&main_function_name)
172 .build(),
173 ];
174
175 let input_assembly_info = vk::PipelineInputAssemblyStateCreateInfo::builder()
176 .topology(vk::PrimitiveTopology::TRIANGLE_LIST);
177 let viewport_info = vk::PipelineViewportStateCreateInfo::builder()
178 .viewport_count(1)
179 .scissor_count(1);
180 let rasterization_info = vk::PipelineRasterizationStateCreateInfo::builder()
181 .depth_clamp_enable(false)
182 .rasterizer_discard_enable(false)
183 .polygon_mode(vk::PolygonMode::FILL)
184 .cull_mode(vk::CullModeFlags::NONE)
185 .front_face(vk::FrontFace::COUNTER_CLOCKWISE)
186 .depth_bias_enable(false)
187 .line_width(1.0);
188 let depth_stencil_info = vk::PipelineDepthStencilStateCreateInfo::builder()
189 .depth_test_enable(false)
190 .depth_write_enable(false)
191 .depth_compare_op(vk::CompareOp::ALWAYS)
192 .depth_bounds_test_enable(false)
193 .stencil_test_enable(false)
194 .front(vk::StencilOpState {
195 compare_op: vk::CompareOp::ALWAYS,
196 fail_op: vk::StencilOp::KEEP,
197 pass_op: vk::StencilOp::KEEP,
198 ..Default::default()
199 })
200 .back(vk::StencilOpState {
201 compare_op: vk::CompareOp::ALWAYS,
202 fail_op: vk::StencilOp::KEEP,
203 pass_op: vk::StencilOp::KEEP,
204 ..Default::default()
205 });
206 let dynamic_states = [vk::DynamicState::VIEWPORT, vk::DynamicState::SCISSOR];
207 let dynamic_state_info =
208 vk::PipelineDynamicStateCreateInfo::builder().dynamic_states(&dynamic_states);
209 let multisample_info = vk::PipelineMultisampleStateCreateInfo::builder()
210 .rasterization_samples(vk::SampleCountFlags::TYPE_1);
211
212 let pipeline = unsafe {
213 device.create_graphics_pipelines(
214 vk::PipelineCache::null(),
215 std::slice::from_ref(
216 &vk::GraphicsPipelineCreateInfo::builder()
217 .stages(&pipeline_shader_stages)
218 .vertex_input_state(
219 &vk::PipelineVertexInputStateCreateInfo::builder()
220 .vertex_attribute_descriptions(&attributes)
221 .vertex_binding_descriptions(std::slice::from_ref(
222 &vk::VertexInputBindingDescription::builder()
223 .binding(0)
224 .input_rate(vk::VertexInputRate::VERTEX)
225 .stride(
226 4 * std::mem::size_of::<f32>() as u32
227 + 4 * std::mem::size_of::<u8>() as u32,
228 ),
229 )),
230 )
231 .input_assembly_state(&input_assembly_info)
232 .viewport_state(&viewport_info)
233 .rasterization_state(&rasterization_info)
234 .multisample_state(&multisample_info)
235 .depth_stencil_state(&depth_stencil_info)
236 .color_blend_state(
237 &vk::PipelineColorBlendStateCreateInfo::builder().attachments(
238 std::slice::from_ref(
239 &vk::PipelineColorBlendAttachmentState::builder()
240 .color_write_mask(
241 vk::ColorComponentFlags::R
242 | vk::ColorComponentFlags::G
243 | vk::ColorComponentFlags::B
244 | vk::ColorComponentFlags::A,
245 )
246 .blend_enable(true)
247 .src_color_blend_factor(vk::BlendFactor::ONE)
248 .dst_color_blend_factor(
249 vk::BlendFactor::ONE_MINUS_SRC_ALPHA,
250 ),
251 ),
252 ),
253 )
254 .dynamic_state(&dynamic_state_info)
255 .layout(pipeline_layout)
256 .render_pass(render_pass)
257 .subpass(0),
258 ),
259 None,
260 )
261 }
262 .expect("Failed to create graphics pipeline.")[0];
263 unsafe {
264 device.destroy_shader_module(vertex_shader_module, None);
265 device.destroy_shader_module(fragment_shader_module, None);
266 }
267 pipeline
268 }
269
270 fn create_framebuffers(
271 device: &Device,
272 swap_images: &[vk::Image],
273 render_pass: vk::RenderPass,
274 surface_format: vk::Format,
275 width: u32,
276 height: u32,
277 ) -> (Vec<vk::Framebuffer>, Vec<vk::ImageView>) {
278 let swapchain_image_views = swap_images
279 .iter()
280 .map(|swapchain_image| unsafe {
281 device
282 .create_image_view(
283 &vk::ImageViewCreateInfo::builder()
284 .image(swapchain_image.clone())
285 .view_type(vk::ImageViewType::TYPE_2D)
286 .format(surface_format)
287 .subresource_range(
288 *vk::ImageSubresourceRange::builder()
289 .aspect_mask(vk::ImageAspectFlags::COLOR)
290 .base_mip_level(0)
291 .level_count(1)
292 .base_array_layer(0)
293 .layer_count(1),
294 ),
295 None,
296 )
297 .expect("Failed to create image view.")
298 })
299 .collect::<Vec<_>>();
300 let framebuffers = swapchain_image_views
301 .iter()
302 .map(|&image_views| unsafe {
303 let attachments = &[image_views];
304 device
305 .create_framebuffer(
306 &vk::FramebufferCreateInfo::builder()
307 .render_pass(render_pass)
308 .attachments(attachments)
309 .width(width)
310 .height(height)
311 .layers(1),
312 None,
313 )
314 .expect("Failed to create framebuffer.")
315 })
316 .collect::<Vec<_>>();
317
318 (framebuffers, swapchain_image_views)
319 }
320
321 fn create_buffers(
322 device: &Device,
323 swapchain_count: usize,
324 allocator: &A,
325 ) -> (
326 Vec<vk::Buffer>,
327 Vec<A::Allocation>,
328 Vec<vk::Buffer>,
329 Vec<A::Allocation>,
330 ) {
331 let mut vertex_buffers = vec![];
332 let mut vertex_buffer_allocations = vec![];
333 let mut index_buffers = vec![];
334 let mut index_buffer_allocations = vec![];
335 for _ in 0..swapchain_count {
336 let vertex_buffer = unsafe {
337 device
338 .create_buffer(
339 &vk::BufferCreateInfo::builder()
340 .usage(vk::BufferUsageFlags::VERTEX_BUFFER)
341 .sharing_mode(vk::SharingMode::EXCLUSIVE)
342 .size(Self::vertex_buffer_size()),
343 None,
344 )
345 .expect("Failed to create vertex buffer.")
346 };
347 let vertex_buffer_requirements =
348 unsafe { device.get_buffer_memory_requirements(vertex_buffer) };
349 let vertex_buffer_allocation = allocator
350 .allocate(A::AllocationCreateInfo::new(
351 Some("egui-ash vertex buffer"),
352 vertex_buffer_requirements,
353 MemoryLocation::cpu_to_gpu(),
354 true,
355 ))
356 .expect("Failed to create vertex buffer.");
357 unsafe {
358 device
359 .bind_buffer_memory(
360 vertex_buffer,
361 vertex_buffer_allocation.memory(),
362 vertex_buffer_allocation.offset(),
363 )
364 .expect("Failed to create vertex buffer.")
365 }
366
367 let index_buffer = unsafe {
368 device
369 .create_buffer(
370 &vk::BufferCreateInfo::builder()
371 .usage(vk::BufferUsageFlags::INDEX_BUFFER)
372 .sharing_mode(vk::SharingMode::EXCLUSIVE)
373 .size(Self::index_buffer_size()),
374 None,
375 )
376 .expect("Failed to create index buffer.")
377 };
378 let index_buffer_requirements =
379 unsafe { device.get_buffer_memory_requirements(index_buffer) };
380 let index_buffer_allocation = allocator
381 .allocate(A::AllocationCreateInfo::new(
382 Some("egui-ash index buffer"),
383 index_buffer_requirements,
384 MemoryLocation::cpu_to_gpu(),
385 true,
386 ))
387 .expect("Failed to create index buffer.");
388 unsafe {
389 device
390 .bind_buffer_memory(
391 index_buffer,
392 index_buffer_allocation.memory(),
393 index_buffer_allocation.offset(),
394 )
395 .expect("Failed to create index buffer.")
396 }
397
398 vertex_buffers.push(vertex_buffer);
399 vertex_buffer_allocations.push(vertex_buffer_allocation);
400 index_buffers.push(index_buffer);
401 index_buffer_allocations.push(index_buffer_allocation);
402 }
403
404 (
405 vertex_buffers,
406 vertex_buffer_allocations,
407 index_buffers,
408 index_buffer_allocations,
409 )
410 }
411
412 fn update_swapchain(
413 &mut self,
414 width: u32,
415 height: u32,
416 swapchain_images: Vec<vk::Image>,
417 surface_format: vk::Format,
418 scale_factor: f32,
419 physical_size: winit::dpi::PhysicalSize<u32>,
420 allocator: A,
421 ) {
422 unsafe {
424 self.device
425 .device_wait_idle()
426 .expect("Failed to wait device idle.");
427 }
428
429 let (render_pass, pipeline_layout, pipeline) = {
431 let Ok(mut state) = self.state.lock() else {
432 panic!("Failed to lock state.");
433 };
434 if let Some(mut state) = state.take() {
435 unsafe {
436 for vertex_buffer in state.vertex_buffers.drain(..) {
437 self.device.destroy_buffer(vertex_buffer, None);
438 }
439 for vertex_buffer_allocation in state.vertex_buffer_allocations.drain(..) {
440 self.allocator
441 .free(vertex_buffer_allocation)
442 .expect("Failed to free vertex buffer allocation.");
443 }
444 for index_buffer in state.index_buffers.drain(..) {
445 self.device.destroy_buffer(index_buffer, None);
446 }
447 for index_buffer_allocation in state.index_buffer_allocations.drain(..) {
448 self.allocator
449 .free(index_buffer_allocation)
450 .expect("Failed to free index buffer allocation.");
451 }
452 for framebuffer in state.framebuffers.drain(..) {
453 self.device.destroy_framebuffer(framebuffer, None);
454 }
455 for image_view in state.swapchain_image_views.drain(..) {
456 self.device.destroy_image_view(image_view, None);
457 }
458 }
459
460 (state.render_pass, state.pipeline_layout, state.pipeline)
461 } else {
462 let render_pass = Self::create_render_pass(&self.device, surface_format);
463 let pipeline_layout =
464 Self::create_pipeline_layout(&self.device, self.descriptor_set_layout);
465 let pipeline = Self::create_pipeline(&self.device, render_pass, pipeline_layout);
466 (render_pass, pipeline_layout, pipeline)
467 }
468 };
469
470 let (framebuffers, swapchain_image_views) = Self::create_framebuffers(
472 &self.device,
473 &swapchain_images,
474 render_pass,
475 surface_format,
476 width,
477 height,
478 );
479
480 let (vertex_buffers, vertex_buffer_allocations, index_buffers, index_buffer_allocations) =
481 Self::create_buffers(&self.device, swapchain_images.len(), &allocator);
482
483 let mut state = self.state.lock().expect("Failed to lock state.");
485 *state = Some(ViewportRendererState {
486 width,
487 height,
488 render_pass,
489 pipeline_layout,
490 pipeline,
491 swapchain_image_views,
492 framebuffers,
493 vertex_buffers,
494 vertex_buffer_allocations,
495 index_buffers,
496 index_buffer_allocations,
497 scale_factor,
498 physical_width: physical_size.width,
499 physical_height: physical_size.height,
500 });
501 }
502
503 fn vertex_buffer_size() -> u64 {
505 1024 * 1024 * 4
506 }
507
508 fn index_buffer_size() -> u64 {
510 1024 * 1024 * 4
511 }
512
513 fn create_egui_cmd(
514 &self,
515 clipped_primitives: Vec<egui::ClippedPrimitive>,
516 textures_delta: egui::TexturesDelta,
517 managed_textures: Arc<Mutex<ManagedTextures<A>>>,
518 user_textures: Arc<Mutex<UserTextures>>,
519 scale_factor: f32,
520 physical_size: winit::dpi::PhysicalSize<u32>,
521 ) -> EguiCommand {
522 EguiCommand {
523 swapchain_recreate_required: {
524 let this = self.clone();
525 let state = this.state.lock().unwrap();
526 if let Some(state) = &*state {
527 state.scale_factor != scale_factor
528 } else {
529 false
530 }
531 },
532 swapchain_updater: Some(Box::new({
533 let mut this = self.clone();
534 move |swapchain_update_info| {
535 let SwapchainUpdateInfo {
536 width,
537 height,
538 swapchain_images,
539 surface_format,
540 } = swapchain_update_info;
541 this.update_swapchain(
542 width,
543 height,
544 swapchain_images,
545 surface_format,
546 scale_factor,
547 physical_size,
548 this.allocator.clone(),
549 );
550 }
551 })),
552 recorder: Box::new({
553 let this = self.clone();
554 move |cmd, index: usize| {
555 let state = this.state.lock().expect("Failed to lock state mutex.");
556 let state = state.as_ref().expect("State is none.");
557 let mut managed_textures =
558 managed_textures.lock().expect("Failed to lock textures.");
559 let mut user_textures =
560 user_textures.lock().expect("Failed to lock user textures.");
561
562 managed_textures.update_textures(textures_delta);
564 user_textures.update_textures();
565
566 let mut vertex_buffer_ptr = state.vertex_buffer_allocations[index]
568 .mapped_ptr()
569 .unwrap()
570 .as_ptr() as *mut u8;
571 let vertex_buffer_ptr_end =
572 unsafe { vertex_buffer_ptr.add(Self::vertex_buffer_size() as usize) };
573 let mut index_buffer_ptr = state.index_buffer_allocations[index]
574 .mapped_ptr()
575 .unwrap()
576 .as_ptr() as *mut u8;
577 let index_buffer_ptr_end =
578 unsafe { index_buffer_ptr.add(Self::index_buffer_size() as usize) };
579
580 unsafe {
582 this.device.cmd_begin_render_pass(
583 cmd,
584 &vk::RenderPassBeginInfo::builder()
585 .render_pass(state.render_pass)
586 .framebuffer(state.framebuffers[index])
587 .clear_values(&[])
588 .render_area(
589 *vk::Rect2D::builder().extent(
590 *vk::Extent2D::builder()
591 .width(state.width)
592 .height(state.height),
593 ),
594 ),
595 vk::SubpassContents::INLINE,
596 );
597 }
598
599 unsafe {
601 this.device.cmd_bind_pipeline(
602 cmd,
603 vk::PipelineBindPoint::GRAPHICS,
604 state.pipeline,
605 );
606 this.device.cmd_bind_vertex_buffers(
607 cmd,
608 0,
609 &[state.vertex_buffers[index]],
610 &[0],
611 );
612 this.device.cmd_bind_index_buffer(
613 cmd,
614 state.index_buffers[index],
615 0,
616 vk::IndexType::UINT32,
617 );
618 let width_points = state.physical_width as f32 / state.scale_factor;
619 let height_points = state.physical_height as f32 / state.scale_factor;
620 this.device.cmd_push_constants(
621 cmd,
622 state.pipeline_layout,
623 vk::ShaderStageFlags::VERTEX,
624 0,
625 bytes_of(&width_points),
626 );
627 this.device.cmd_push_constants(
628 cmd,
629 state.pipeline_layout,
630 vk::ShaderStageFlags::VERTEX,
631 4,
632 bytes_of(&height_points),
633 );
634 }
635
636 let mut vertex_base = 0;
638 let mut index_base = 0;
639 for egui::ClippedPrimitive {
640 clip_rect,
641 primitive,
642 } in clipped_primitives
643 {
644 let mesh = match primitive {
645 egui::epaint::Primitive::Mesh(mesh) => mesh,
646 egui::epaint::Primitive::Callback(_) => todo!(),
647 };
648 if mesh.vertices.is_empty() || mesh.indices.is_empty() {
649 continue;
650 }
651
652 unsafe {
653 match mesh.texture_id {
654 egui::TextureId::User(id) => {
655 if let Some(&descriptor_set) =
656 user_textures.texture_desc_sets.get(&id)
657 {
658 this.device.cmd_bind_descriptor_sets(
659 cmd,
660 vk::PipelineBindPoint::GRAPHICS,
661 state.pipeline_layout,
662 0,
663 &[descriptor_set],
664 &[],
665 );
666 } else {
667 log::error!(
668 "This UserTexture has already been unregistered: {:?}",
669 mesh.texture_id
670 );
671 continue;
672 }
673 }
674 egui::TextureId::Managed(_) => {
675 this.device.cmd_bind_descriptor_sets(
676 cmd,
677 vk::PipelineBindPoint::GRAPHICS,
678 state.pipeline_layout,
679 0,
680 &[*managed_textures
681 .texture_desc_sets
682 .get(&mesh.texture_id)
683 .unwrap()],
684 &[],
685 );
686 }
687 }
688 }
689 let v_slice = &mesh.vertices;
690 let v_size = std::mem::size_of::<egui::epaint::Vertex>();
691 let v_copy_size = v_slice.len() * v_size;
692
693 let i_slice = &mesh.indices;
694 let i_size = std::mem::size_of::<u32>();
695 let i_copy_size = i_slice.len() * i_size;
696
697 let vertex_buffer_ptr_next = unsafe { vertex_buffer_ptr.add(v_copy_size) };
698 let index_buffer_ptr_next = unsafe { index_buffer_ptr.add(i_copy_size) };
699
700 if vertex_buffer_ptr_next >= vertex_buffer_ptr_end
701 || index_buffer_ptr_next >= index_buffer_ptr_end
702 {
703 panic!("egui paint out of memory");
704 }
705
706 unsafe {
708 vertex_buffer_ptr.copy_from(v_slice.as_ptr() as *const u8, v_copy_size)
709 };
710 unsafe {
711 index_buffer_ptr.copy_from(i_slice.as_ptr() as *const u8, i_copy_size)
712 };
713
714 vertex_buffer_ptr = vertex_buffer_ptr_next;
715 index_buffer_ptr = index_buffer_ptr_next;
716
717 unsafe {
719 let min = clip_rect.min;
720 let min = egui::Pos2 {
721 x: min.x * state.scale_factor as f32,
722 y: min.y * state.scale_factor as f32,
723 };
724 let min = egui::Pos2 {
725 x: f32::clamp(min.x, 0.0, state.physical_width as f32),
726 y: f32::clamp(min.y, 0.0, state.physical_height as f32),
727 };
728 let max = clip_rect.max;
729 let max = egui::Pos2 {
730 x: max.x * state.scale_factor as f32,
731 y: max.y * state.scale_factor as f32,
732 };
733 let max = egui::Pos2 {
734 x: f32::clamp(max.x, min.x, state.physical_width as f32),
735 y: f32::clamp(max.y, min.y, state.physical_height as f32),
736 };
737 this.device.cmd_set_scissor(
738 cmd,
739 0,
740 std::slice::from_ref(
741 &vk::Rect2D::builder()
742 .offset(vk::Offset2D {
743 x: min.x.round() as i32,
744 y: min.y.round() as i32,
745 })
746 .extent(vk::Extent2D {
747 width: (max.x.round() - min.x) as u32,
748 height: (max.y.round() - min.y) as u32,
749 }),
750 ),
751 );
752 this.device.cmd_set_viewport(
753 cmd,
754 0,
755 std::slice::from_ref(
756 &vk::Viewport::builder()
757 .x(0.0)
758 .y(0.0)
759 .width(state.physical_width as f32)
760 .height(state.physical_height as f32)
761 .min_depth(0.0)
762 .max_depth(1.0),
763 ),
764 );
765 this.device.cmd_draw_indexed(
766 cmd,
767 mesh.indices.len() as u32,
768 1,
769 index_base,
770 vertex_base,
771 0,
772 );
773 }
774
775 vertex_base += mesh.vertices.len() as i32;
776 index_base += mesh.indices.len() as u32;
777 }
778
779 unsafe {
781 this.device.cmd_end_render_pass(cmd);
782 }
783 }
784 }),
785 }
786 }
787
788 fn destroy(&mut self) {
789 let mut state = self.state.lock().expect("Failed to lock state mutex.");
790 if let Some(mut state) = state.take() {
791 unsafe {
793 self.device
794 .device_wait_idle()
795 .expect("Failed to wait device idle")
796 };
797
798 unsafe {
800 for image_view in state.swapchain_image_views.drain(..) {
801 self.device.destroy_image_view(image_view, None);
802 }
803 self.device.destroy_render_pass(state.render_pass, None);
804 for vertex_buffer in state.vertex_buffers.drain(..) {
805 self.device.destroy_buffer(vertex_buffer, None);
806 }
807 for vertex_buffer_allocation in state.vertex_buffer_allocations.drain(..) {
808 self.allocator
809 .free(vertex_buffer_allocation)
810 .expect("Failed to free vertex buffer allocation.");
811 }
812 for index_buffer in state.index_buffers.drain(..) {
813 self.device.destroy_buffer(index_buffer, None);
814 }
815 for index_buffer_allocation in state.index_buffer_allocations.drain(..) {
816 self.allocator
817 .free(index_buffer_allocation)
818 .expect("Failed to free index buffer allocation.");
819 }
820 for framebuffer in state.framebuffers.drain(..) {
821 self.device.destroy_framebuffer(framebuffer, None);
822 }
823 for image_view in state.swapchain_image_views.drain(..) {
824 self.device.destroy_image_view(image_view, None);
825 }
826 self.device.destroy_pipeline(state.pipeline, None);
827 self.device
828 .destroy_pipeline_layout(state.pipeline_layout, None);
829 }
830 }
831 }
832}
833
834struct ManagedTextures<A: Allocator + 'static> {
835 device: Device,
836 queue: vk::Queue,
837 queue_family_index: u32,
838 descriptor_pool: vk::DescriptorPool,
839 descriptor_set_layout: vk::DescriptorSetLayout,
840 sampler: vk::Sampler,
841 allocator: A,
842
843 texture_desc_sets: HashMap<egui::TextureId, vk::DescriptorSet>,
844 texture_images: HashMap<egui::TextureId, vk::Image>,
845 texture_allocations: HashMap<egui::TextureId, A::Allocation>,
846 texture_image_views: HashMap<egui::TextureId, vk::ImageView>,
847}
848impl<A: Allocator + 'static> ManagedTextures<A> {
849 fn create_sampler(device: &Device) -> vk::Sampler {
850 unsafe {
851 device.create_sampler(
852 &vk::SamplerCreateInfo::builder()
853 .address_mode_u(vk::SamplerAddressMode::CLAMP_TO_EDGE)
854 .address_mode_v(vk::SamplerAddressMode::CLAMP_TO_EDGE)
855 .address_mode_w(vk::SamplerAddressMode::CLAMP_TO_EDGE)
856 .anisotropy_enable(false)
857 .min_filter(vk::Filter::LINEAR)
858 .mag_filter(vk::Filter::LINEAR)
859 .mipmap_mode(vk::SamplerMipmapMode::LINEAR)
860 .min_lod(0.0)
861 .max_lod(vk::LOD_CLAMP_NONE),
862 None,
863 )
864 }
865 .expect("Failed to create sampler.")
866 }
867
868 fn new(
869 device: Device,
870 queue: vk::Queue,
871 queue_family_index: u32,
872 descriptor_pool: vk::DescriptorPool,
873 descriptor_set_layout: vk::DescriptorSetLayout,
874 allocator: A,
875 ) -> Arc<Mutex<Self>> {
876 let sampler = Self::create_sampler(&device);
877
878 Arc::new(Mutex::new(Self {
879 device,
880 queue,
881 queue_family_index,
882 descriptor_pool,
883 descriptor_set_layout,
884 sampler,
885 allocator,
886 texture_desc_sets: HashMap::new(),
887 texture_images: HashMap::new(),
888 texture_allocations: HashMap::new(),
889 texture_image_views: HashMap::new(),
890 }))
891 }
892
893 fn update_texture(&mut self, texture_id: egui::TextureId, delta: egui::epaint::ImageDelta) {
894 let data: Vec<u8> = match &delta.image {
896 egui::ImageData::Color(image) => {
897 assert_eq!(
898 image.width() * image.height(),
899 image.pixels.len(),
900 "Mismatch between texture size and texel count"
901 );
902 image
903 .pixels
904 .iter()
905 .flat_map(|color| color.to_array())
906 .collect()
907 }
908 egui::ImageData::Font(image) => image
909 .srgba_pixels(None)
910 .flat_map(|color| color.to_array())
911 .collect(),
912 };
913 let cmd_pool = {
914 unsafe {
915 self.device
916 .create_command_pool(
917 &vk::CommandPoolCreateInfo::builder()
918 .queue_family_index(self.queue_family_index),
919 None,
920 )
921 .unwrap()
922 }
923 };
924 let cmd = {
925 unsafe {
926 self.device
927 .allocate_command_buffers(
928 &vk::CommandBufferAllocateInfo::builder()
929 .command_buffer_count(1u32)
930 .command_pool(cmd_pool)
931 .level(vk::CommandBufferLevel::PRIMARY),
932 )
933 .unwrap()[0]
934 }
935 };
936 let cmd_fence = unsafe {
937 self.device
938 .create_fence(&vk::FenceCreateInfo::builder(), None)
939 .unwrap()
940 };
941
942 let (staging_buffer, staging_allocation) = {
943 let buffer_size = data.len() as vk::DeviceSize;
944 let buffer_info = vk::BufferCreateInfo::builder()
945 .size(buffer_size)
946 .usage(vk::BufferUsageFlags::TRANSFER_SRC);
947 let texture_buffer = unsafe { self.device.create_buffer(&buffer_info, None) }.unwrap();
948 let requirements =
949 unsafe { self.device.get_buffer_memory_requirements(texture_buffer) };
950 let allocation = self
951 .allocator
952 .allocate(A::AllocationCreateInfo::new(
953 Some("egui-ash image staging buffer"),
954 requirements,
955 MemoryLocation::cpu_to_gpu(),
956 true,
957 ))
958 .unwrap();
959 unsafe {
960 self.device
961 .bind_buffer_memory(texture_buffer, allocation.memory(), allocation.offset())
962 .unwrap()
963 };
964 (texture_buffer, allocation)
965 };
966 let ptr = staging_allocation.mapped_ptr().unwrap().as_ptr() as *mut u8;
967 unsafe {
968 ptr.copy_from_nonoverlapping(data.as_ptr(), data.len());
969 }
970 let (texture_image, texture_allocation) = {
971 let extent = vk::Extent3D {
972 width: delta.image.width() as u32,
973 height: delta.image.height() as u32,
974 depth: 1,
975 };
976 let handle = unsafe {
977 self.device.create_image(
978 &vk::ImageCreateInfo::builder()
979 .array_layers(1)
980 .extent(extent)
981 .flags(vk::ImageCreateFlags::empty())
982 .format(vk::Format::R8G8B8A8_UNORM)
983 .image_type(vk::ImageType::TYPE_2D)
984 .initial_layout(vk::ImageLayout::UNDEFINED)
985 .mip_levels(1)
986 .samples(vk::SampleCountFlags::TYPE_1)
987 .sharing_mode(vk::SharingMode::EXCLUSIVE)
988 .tiling(vk::ImageTiling::OPTIMAL)
989 .usage(
990 vk::ImageUsageFlags::SAMPLED
991 | vk::ImageUsageFlags::TRANSFER_DST
992 | vk::ImageUsageFlags::TRANSFER_SRC,
993 ),
994 None,
995 )
996 }
997 .unwrap();
998 let requirements = unsafe { self.device.get_image_memory_requirements(handle) };
999 let allocation = self
1000 .allocator
1001 .allocate(A::AllocationCreateInfo::new(
1002 Some("egui-ash image buffer"),
1003 requirements,
1004 MemoryLocation::gpu_only(),
1005 false,
1006 ))
1007 .unwrap();
1008 unsafe {
1009 self.device
1010 .bind_image_memory(handle, allocation.memory(), allocation.offset())
1011 .unwrap()
1012 };
1013 (handle, allocation)
1014 };
1015 let texture_image_view = {
1016 unsafe {
1017 self.device
1018 .create_image_view(
1019 &vk::ImageViewCreateInfo::builder()
1020 .components(vk::ComponentMapping::default())
1021 .flags(vk::ImageViewCreateFlags::empty())
1022 .format(vk::Format::R8G8B8A8_UNORM)
1023 .image(texture_image)
1024 .subresource_range(vk::ImageSubresourceRange {
1025 aspect_mask: vk::ImageAspectFlags::COLOR,
1026 base_array_layer: 0,
1027 base_mip_level: 0,
1028 layer_count: 1,
1029 level_count: 1,
1030 })
1031 .view_type(vk::ImageViewType::TYPE_2D),
1032 None,
1033 )
1034 .unwrap()
1035 }
1036 };
1037
1038 unsafe {
1040 self.device
1041 .begin_command_buffer(
1042 cmd,
1043 &vk::CommandBufferBeginInfo::builder()
1044 .flags(vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT),
1045 )
1046 .unwrap();
1047 }
1048 utils::insert_image_memory_barrier(
1050 &self.device,
1051 &cmd,
1052 &texture_image,
1053 vk::QUEUE_FAMILY_IGNORED,
1054 vk::QUEUE_FAMILY_IGNORED,
1055 vk::AccessFlags::NONE_KHR,
1056 vk::AccessFlags::TRANSFER_WRITE,
1057 vk::ImageLayout::UNDEFINED,
1058 vk::ImageLayout::TRANSFER_DST_OPTIMAL,
1059 vk::PipelineStageFlags::HOST,
1060 vk::PipelineStageFlags::TRANSFER,
1061 vk::ImageSubresourceRange {
1062 aspect_mask: vk::ImageAspectFlags::COLOR,
1063 base_array_layer: 0,
1064 base_mip_level: 0,
1065 layer_count: 1,
1066 level_count: 1,
1067 },
1068 );
1069 unsafe {
1070 self.device.cmd_copy_buffer_to_image(
1071 cmd,
1072 staging_buffer,
1073 texture_image,
1074 vk::ImageLayout::TRANSFER_DST_OPTIMAL,
1075 std::slice::from_ref(
1076 &vk::BufferImageCopy::builder()
1077 .buffer_offset(0)
1078 .buffer_row_length(delta.image.width() as u32)
1079 .buffer_image_height(delta.image.height() as u32)
1080 .image_subresource(vk::ImageSubresourceLayers {
1081 aspect_mask: vk::ImageAspectFlags::COLOR,
1082 base_array_layer: 0,
1083 layer_count: 1,
1084 mip_level: 0,
1085 })
1086 .image_offset(vk::Offset3D { x: 0, y: 0, z: 0 })
1087 .image_extent(vk::Extent3D {
1088 width: delta.image.width() as u32,
1089 height: delta.image.height() as u32,
1090 depth: 1,
1091 }),
1092 ),
1093 );
1094 }
1095 utils::insert_image_memory_barrier(
1096 &self.device,
1097 &cmd,
1098 &texture_image,
1099 vk::QUEUE_FAMILY_IGNORED,
1100 vk::QUEUE_FAMILY_IGNORED,
1101 vk::AccessFlags::TRANSFER_WRITE,
1102 vk::AccessFlags::SHADER_READ,
1103 vk::ImageLayout::TRANSFER_DST_OPTIMAL,
1104 vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
1105 vk::PipelineStageFlags::TRANSFER,
1106 vk::PipelineStageFlags::VERTEX_SHADER,
1107 vk::ImageSubresourceRange {
1108 aspect_mask: vk::ImageAspectFlags::COLOR,
1109 base_array_layer: 0,
1110 base_mip_level: 0,
1111 layer_count: 1,
1112 level_count: 1,
1113 },
1114 );
1115
1116 unsafe {
1117 self.device.end_command_buffer(cmd).unwrap();
1118 }
1119 let cmd_buffs = [cmd];
1120 unsafe {
1121 self.device
1122 .queue_submit(
1123 self.queue,
1124 std::slice::from_ref(&vk::SubmitInfo::builder().command_buffers(&cmd_buffs)),
1125 cmd_fence,
1126 )
1127 .unwrap();
1128 self.device
1129 .wait_for_fences(&[cmd_fence], true, u64::MAX)
1130 .unwrap();
1131 }
1132
1133 if let Some(pos) = delta.pos {
1136 let existing_texture = self.texture_images.get(&texture_id);
1138 if let Some(existing_texture) = existing_texture {
1139 let extent = vk::Extent3D {
1140 width: delta.image.width() as u32,
1141 height: delta.image.height() as u32,
1142 depth: 1,
1143 };
1144 unsafe {
1145 self.device
1146 .reset_command_pool(cmd_pool, vk::CommandPoolResetFlags::empty())
1147 .unwrap();
1148 self.device.reset_fences(&[cmd_fence]).unwrap();
1149
1150 self.device
1152 .begin_command_buffer(
1153 cmd,
1154 &vk::CommandBufferBeginInfo::builder()
1155 .flags(vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT),
1156 )
1157 .unwrap();
1158
1159 utils::insert_image_memory_barrier(
1161 &self.device,
1162 &cmd,
1163 &existing_texture,
1164 vk::QUEUE_FAMILY_IGNORED,
1165 vk::QUEUE_FAMILY_IGNORED,
1166 vk::AccessFlags::SHADER_READ,
1167 vk::AccessFlags::TRANSFER_WRITE,
1168 vk::ImageLayout::UNDEFINED,
1169 vk::ImageLayout::TRANSFER_DST_OPTIMAL,
1170 vk::PipelineStageFlags::FRAGMENT_SHADER,
1171 vk::PipelineStageFlags::TRANSFER,
1172 vk::ImageSubresourceRange {
1173 aspect_mask: vk::ImageAspectFlags::COLOR,
1174 base_mip_level: 0,
1175 level_count: 1,
1176 base_array_layer: 0,
1177 layer_count: 1,
1178 },
1179 );
1180 utils::insert_image_memory_barrier(
1182 &self.device,
1183 &cmd,
1184 &texture_image,
1185 vk::QUEUE_FAMILY_IGNORED,
1186 vk::QUEUE_FAMILY_IGNORED,
1187 vk::AccessFlags::SHADER_READ,
1188 vk::AccessFlags::TRANSFER_READ,
1189 vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
1190 vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
1191 vk::PipelineStageFlags::FRAGMENT_SHADER,
1192 vk::PipelineStageFlags::TRANSFER,
1193 vk::ImageSubresourceRange {
1194 aspect_mask: vk::ImageAspectFlags::COLOR,
1195 base_mip_level: 0,
1196 level_count: 1,
1197 base_array_layer: 0,
1198 layer_count: 1,
1199 },
1200 );
1201 let top_left = vk::Offset3D {
1202 x: pos[0] as i32,
1203 y: pos[1] as i32,
1204 z: 0,
1205 };
1206 let bottom_right = vk::Offset3D {
1207 x: pos[0] as i32 + delta.image.width() as i32,
1208 y: pos[1] as i32 + delta.image.height() as i32,
1209 z: 1,
1210 };
1211
1212 let region = vk::ImageBlit {
1213 src_subresource: vk::ImageSubresourceLayers {
1214 aspect_mask: vk::ImageAspectFlags::COLOR,
1215 mip_level: 0,
1216 base_array_layer: 0,
1217 layer_count: 1,
1218 },
1219 src_offsets: [
1220 vk::Offset3D { x: 0, y: 0, z: 0 },
1221 vk::Offset3D {
1222 x: extent.width as i32,
1223 y: extent.height as i32,
1224 z: extent.depth as i32,
1225 },
1226 ],
1227 dst_subresource: vk::ImageSubresourceLayers {
1228 aspect_mask: vk::ImageAspectFlags::COLOR,
1229 mip_level: 0,
1230 base_array_layer: 0,
1231 layer_count: 1,
1232 },
1233 dst_offsets: [top_left, bottom_right],
1234 };
1235 self.device.cmd_blit_image(
1236 cmd,
1237 texture_image,
1238 vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
1239 *existing_texture,
1240 vk::ImageLayout::TRANSFER_DST_OPTIMAL,
1241 &[region],
1242 vk::Filter::NEAREST,
1243 );
1244
1245 utils::insert_image_memory_barrier(
1247 &self.device,
1248 &cmd,
1249 &existing_texture,
1250 vk::QUEUE_FAMILY_IGNORED,
1251 vk::QUEUE_FAMILY_IGNORED,
1252 vk::AccessFlags::TRANSFER_WRITE,
1253 vk::AccessFlags::SHADER_READ,
1254 vk::ImageLayout::TRANSFER_DST_OPTIMAL,
1255 vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
1256 vk::PipelineStageFlags::TRANSFER,
1257 vk::PipelineStageFlags::FRAGMENT_SHADER,
1258 vk::ImageSubresourceRange {
1259 aspect_mask: vk::ImageAspectFlags::COLOR,
1260 base_mip_level: 0,
1261 level_count: 1,
1262 base_array_layer: 0,
1263 layer_count: 1,
1264 },
1265 );
1266 self.device.end_command_buffer(cmd).unwrap();
1267 let cmd_buffs = [cmd];
1268 self.device
1269 .queue_submit(
1270 self.queue,
1271 std::slice::from_ref(
1272 &vk::SubmitInfo::builder().command_buffers(&cmd_buffs),
1273 ),
1274 cmd_fence,
1275 )
1276 .unwrap();
1277 self.device
1278 .wait_for_fences(&[cmd_fence], true, u64::MAX)
1279 .unwrap();
1280
1281 self.device.destroy_image(texture_image, None);
1283 self.device.destroy_image_view(texture_image_view, None);
1284 self.allocator.free(texture_allocation).unwrap();
1285 }
1286 } else {
1287 return;
1288 }
1289 } else {
1290 let dsc_set = {
1294 unsafe {
1295 self.device
1296 .allocate_descriptor_sets(
1297 &vk::DescriptorSetAllocateInfo::builder()
1298 .descriptor_pool(self.descriptor_pool)
1299 .set_layouts(&[self.descriptor_set_layout]),
1300 )
1301 .unwrap()[0]
1302 }
1303 };
1304 unsafe {
1305 self.device.update_descriptor_sets(
1306 std::slice::from_ref(
1307 &vk::WriteDescriptorSet::builder()
1308 .dst_set(dsc_set)
1309 .descriptor_type(vk::DescriptorType::COMBINED_IMAGE_SAMPLER)
1310 .dst_array_element(0_u32)
1311 .dst_binding(0_u32)
1312 .image_info(std::slice::from_ref(
1313 &vk::DescriptorImageInfo::builder()
1314 .image_view(texture_image_view)
1315 .image_layout(vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL)
1316 .sampler(self.sampler),
1317 )),
1318 ),
1319 &[],
1320 );
1321 }
1322 if let Some((_, image)) = self.texture_images.remove_entry(&texture_id) {
1324 unsafe {
1325 self.device.destroy_image(image, None);
1326 }
1327 }
1328 if let Some((_, image_view)) = self.texture_image_views.remove_entry(&texture_id) {
1329 unsafe {
1330 self.device.destroy_image_view(image_view, None);
1331 }
1332 }
1333 self.texture_images.insert(texture_id, texture_image);
1335 self.texture_allocations
1336 .insert(texture_id, texture_allocation);
1337 self.texture_image_views
1338 .insert(texture_id, texture_image_view);
1339 self.texture_desc_sets.insert(texture_id, dsc_set);
1340 }
1341 unsafe {
1343 self.device.destroy_buffer(staging_buffer, None);
1344 self.device.destroy_command_pool(cmd_pool, None);
1345 self.allocator.free(staging_allocation).unwrap();
1346 self.device.destroy_fence(cmd_fence, None);
1347 }
1348 }
1349
1350 fn free_texture(&mut self, id: egui::TextureId) {
1351 self.texture_desc_sets.remove_entry(&id);
1352 if let Some((_, image)) = self.texture_images.remove_entry(&id) {
1353 unsafe {
1354 self.device.destroy_image(image, None);
1355 }
1356 }
1357 if let Some((_, image_view)) = self.texture_image_views.remove_entry(&id) {
1358 unsafe {
1359 self.device.destroy_image_view(image_view, None);
1360 }
1361 }
1362 if let Some((_, allocation)) = self.texture_allocations.remove_entry(&id) {
1363 self.allocator.free(allocation).unwrap();
1364 }
1365 }
1366
1367 fn update_textures(&mut self, textures_delta: egui::TexturesDelta) {
1368 for (id, image_delta) in textures_delta.set {
1369 self.update_texture(id, image_delta);
1370 }
1371 for id in textures_delta.free {
1372 self.free_texture(id);
1373 }
1374 }
1375
1376 fn destroy(&mut self, device: &Device, allocator: &A) {
1377 unsafe {
1379 device
1380 .device_wait_idle()
1381 .expect("Failed to wait device idle")
1382 };
1383
1384 unsafe {
1386 for (_, image) in self.texture_images.drain() {
1387 device.destroy_image(image, None);
1388 }
1389 for (_, image_view) in self.texture_image_views.drain() {
1390 device.destroy_image_view(image_view, None);
1391 }
1392 for (_, allocation) in self.texture_allocations.drain() {
1393 allocator.free(allocation).unwrap();
1394 }
1395 self.device.destroy_sampler(self.sampler, None);
1396 }
1397 }
1398}
1399
1400pub(crate) type ImageRegistryReceiver = Receiver<RegistryCommand>;
1401
1402#[derive(Clone)]
1403pub struct ImageRegistry {
1404 sender: Sender<RegistryCommand>,
1405 counter: Arc<AtomicU64>,
1406}
1407impl ImageRegistry {
1408 pub(crate) fn new() -> (Self, ImageRegistryReceiver) {
1409 let (sender, receiver) = mpsc::channel();
1410 (
1411 Self {
1412 sender,
1413 counter: Arc::new(AtomicU64::new(0)),
1414 },
1415 receiver,
1416 )
1417 }
1418
1419 pub fn register_user_texture(
1420 &self,
1421 image_view: vk::ImageView,
1422 sampler: vk::Sampler,
1423 ) -> egui::TextureId {
1424 let id = egui::TextureId::User(self.counter.fetch_add(1, Ordering::SeqCst));
1425 self.sender
1426 .send(RegistryCommand::RegisterUserTexture {
1427 image_view,
1428 sampler,
1429 id,
1430 })
1431 .expect("Failed to send register user texture command.");
1432 id
1433 }
1434
1435 pub fn unregister_user_texture(&self, id: egui::TextureId) {
1436 let _ = self
1437 .sender
1438 .send(RegistryCommand::UnregisterUserTexture { id });
1439 }
1440}
1441impl Debug for ImageRegistry {
1442 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1443 f.debug_struct("ImageRegistry").finish()
1444 }
1445}
1446
1447pub(crate) enum RegistryCommand {
1448 RegisterUserTexture {
1449 image_view: vk::ImageView,
1450 sampler: vk::Sampler,
1451 id: egui::TextureId,
1452 },
1453 UnregisterUserTexture {
1454 id: egui::TextureId,
1455 },
1456}
1457
1458struct UserTextures {
1459 device: Device,
1460 descriptor_pool: vk::DescriptorPool,
1461 descriptor_set_layout: vk::DescriptorSetLayout,
1462 texture_desc_sets: HashMap<u64, vk::DescriptorSet>,
1463 receiver: ImageRegistryReceiver,
1464}
1465impl UserTextures {
1466 fn new(
1467 device: Device,
1468 descriptor_pool: vk::DescriptorPool,
1469 descriptor_set_layout: vk::DescriptorSetLayout,
1470 receiver: ImageRegistryReceiver,
1471 ) -> Arc<Mutex<Self>> {
1472 let texture_desc_sets = HashMap::new();
1473
1474 Arc::new(Mutex::new(Self {
1475 device,
1476 descriptor_pool,
1477 descriptor_set_layout,
1478 texture_desc_sets,
1479 receiver,
1480 }))
1481 }
1482
1483 fn register_user_texture(&mut self, id: u64, image_view: vk::ImageView, sampler: vk::Sampler) {
1484 let dsc_set = {
1485 unsafe {
1486 self.texture_desc_sets.insert(
1487 id,
1488 self.device
1489 .allocate_descriptor_sets(
1490 &vk::DescriptorSetAllocateInfo::builder()
1491 .descriptor_pool(self.descriptor_pool)
1492 .set_layouts(&[self.descriptor_set_layout]),
1493 )
1494 .expect("Failed to allocate descriptor set")[0],
1495 );
1496 }
1497 self.texture_desc_sets.get(&id).unwrap()
1498 };
1499 unsafe {
1500 self.device.update_descriptor_sets(
1501 std::slice::from_ref(
1502 &vk::WriteDescriptorSet::builder()
1503 .dst_set(*dsc_set)
1504 .descriptor_type(vk::DescriptorType::COMBINED_IMAGE_SAMPLER)
1505 .dst_array_element(0_u32)
1506 .dst_binding(0_u32)
1507 .image_info(std::slice::from_ref(
1508 &vk::DescriptorImageInfo::builder()
1509 .image_view(image_view)
1510 .image_layout(vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL)
1511 .sampler(sampler),
1512 )),
1513 ),
1514 &[],
1515 );
1516 }
1517 }
1518
1519 fn unregister_user_texture(&mut self, id: u64) {
1520 if let Some(desc_set) = self.texture_desc_sets.remove(&id) {
1521 unsafe {
1522 self.device
1523 .device_wait_idle()
1524 .expect("Failed to wait device idle");
1525 self.device
1526 .free_descriptor_sets(self.descriptor_pool, &[desc_set])
1527 .expect("Failed to free descriptor set.");
1528 }
1529 }
1530 }
1531
1532 fn update_textures(&mut self) {
1533 for command in self.receiver.try_iter().collect::<Vec<_>>() {
1534 match command {
1535 RegistryCommand::RegisterUserTexture {
1536 image_view,
1537 sampler,
1538 id,
1539 } => match id {
1540 egui::TextureId::Managed(_) => {
1541 panic!("This texture id is not for user texture: {:?}", id)
1542 }
1543 egui::TextureId::User(id) => {
1544 self.register_user_texture(id, image_view, sampler);
1545 }
1546 },
1547 RegistryCommand::UnregisterUserTexture { id } => match id {
1548 egui::TextureId::Managed(_) => {
1549 panic!("This texture id is not for user texture: {:?}", id)
1550 }
1551 egui::TextureId::User(id) => {
1552 self.unregister_user_texture(id);
1553 }
1554 },
1555 }
1556 }
1557 }
1558}
1559
1560pub(crate) struct Renderer<A: Allocator + 'static> {
1561 device: Device,
1562 descriptor_pool: vk::DescriptorPool,
1563 descriptor_set_layout: vk::DescriptorSetLayout,
1564 allocator: A,
1565 viewport_renderers: HashMap<egui::ViewportId, ViewportRenderer<A>>,
1566
1567 managed_textures: Arc<Mutex<ManagedTextures<A>>>,
1568 user_textures: Arc<Mutex<UserTextures>>,
1569}
1570impl<A: Allocator + 'static> Renderer<A> {
1571 fn create_descriptor_pool(device: &Device) -> vk::DescriptorPool {
1572 unsafe {
1573 device.create_descriptor_pool(
1574 &vk::DescriptorPoolCreateInfo::builder()
1575 .flags(vk::DescriptorPoolCreateFlags::FREE_DESCRIPTOR_SET)
1576 .max_sets(1024)
1577 .pool_sizes(std::slice::from_ref(
1578 &vk::DescriptorPoolSize::builder()
1579 .ty(vk::DescriptorType::COMBINED_IMAGE_SAMPLER)
1580 .descriptor_count(1024),
1581 )),
1582 None,
1583 )
1584 }
1585 .expect("Failed to create descriptor pool.")
1586 }
1587
1588 fn create_descriptor_set_layout(device: &Device) -> vk::DescriptorSetLayout {
1589 unsafe {
1590 device.create_descriptor_set_layout(
1591 &vk::DescriptorSetLayoutCreateInfo::builder().bindings(std::slice::from_ref(
1592 &vk::DescriptorSetLayoutBinding::builder()
1593 .descriptor_type(vk::DescriptorType::COMBINED_IMAGE_SAMPLER)
1594 .descriptor_count(1)
1595 .binding(0)
1596 .stage_flags(vk::ShaderStageFlags::FRAGMENT),
1597 )),
1598 None,
1599 )
1600 }
1601 .expect("Failed to create descriptor set layout.")
1602 }
1603
1604 pub(crate) fn new(
1605 device: Device,
1606 queue: vk::Queue,
1607 queue_family_index: u32,
1608 allocator: A,
1609 receiver: Receiver<RegistryCommand>,
1610 ) -> Arc<Mutex<Self>> {
1611 let descriptor_pool = Self::create_descriptor_pool(&device);
1612 let descriptor_set_layout = Self::create_descriptor_set_layout(&device);
1613 Arc::new(Mutex::new(Self {
1614 device: device.clone(),
1615 descriptor_pool,
1616 descriptor_set_layout,
1617 allocator: allocator.clone(),
1618 viewport_renderers: HashMap::new(),
1619 managed_textures: ManagedTextures::new(
1620 device.clone(),
1621 queue,
1622 queue_family_index,
1623 descriptor_pool,
1624 descriptor_set_layout,
1625 allocator,
1626 ),
1627 user_textures: UserTextures::new(
1628 device,
1629 descriptor_pool,
1630 descriptor_set_layout,
1631 receiver,
1632 ),
1633 }))
1634 }
1635
1636 pub(crate) fn create_egui_cmd(
1637 &mut self,
1638 viewport_id: egui::ViewportId,
1639 clipped_primitives: Vec<egui::ClippedPrimitive>,
1640 textures_delta: egui::TexturesDelta,
1641 scale_factor: f32,
1642 physical_size: winit::dpi::PhysicalSize<u32>,
1643 ) -> EguiCommand {
1644 let viewport_renderer = self
1645 .viewport_renderers
1646 .entry(viewport_id)
1647 .or_insert_with(|| {
1648 ViewportRenderer::new(
1649 self.device.clone(),
1650 self.descriptor_set_layout,
1651 self.allocator.clone(),
1652 )
1653 });
1654 viewport_renderer.create_egui_cmd(
1655 clipped_primitives,
1656 textures_delta,
1657 self.managed_textures.clone(),
1658 self.user_textures.clone(),
1659 scale_factor,
1660 physical_size,
1661 )
1662 }
1663
1664 pub(crate) fn destroy_viewports(&mut self, active_viewport_ids: &egui::ViewportIdSet) {
1665 let remove_viewports = self
1666 .viewport_renderers
1667 .keys()
1668 .filter(|id| !active_viewport_ids.contains(id))
1669 .filter(|id| id != &&egui::ViewportId::ROOT)
1670 .map(|id| id.clone())
1671 .collect::<Vec<_>>();
1672
1673 for id in remove_viewports {
1674 if let Some(mut viewport_renderer) = self.viewport_renderers.remove(&id) {
1675 viewport_renderer.destroy();
1676 }
1677 }
1678 }
1679
1680 pub(crate) fn destroy_root(&mut self) {
1681 unsafe {
1683 self.device
1684 .device_wait_idle()
1685 .expect("Failed to wait device idle")
1686 };
1687
1688 self.managed_textures
1689 .lock()
1690 .unwrap()
1691 .destroy(&self.device, &self.allocator);
1692 for (_, mut viewport_renderer) in self.viewport_renderers.drain() {
1693 viewport_renderer.destroy();
1694 }
1695 unsafe {
1696 self.device
1697 .destroy_descriptor_set_layout(self.descriptor_set_layout, None);
1698 self.device
1699 .destroy_descriptor_pool(self.descriptor_pool, None);
1700 }
1701 }
1702}
1703
1704pub struct SwapchainUpdateInfo {
1706 pub width: u32,
1707 pub height: u32,
1708 pub swapchain_images: Vec<vk::Image>,
1709 pub surface_format: vk::Format,
1710}
1711
1712pub struct EguiCommand {
1717 swapchain_updater: Option<Box<dyn FnOnce(SwapchainUpdateInfo) + Send>>,
1718 recorder: Box<dyn FnOnce(vk::CommandBuffer, usize) + Send>,
1719 swapchain_recreate_required: bool,
1720}
1721impl EguiCommand {
1722 pub fn update_swapchain(&mut self, info: SwapchainUpdateInfo) {
1725 (self.swapchain_updater.take().expect(
1726 "The swapchain has been updated more than once. Always update swapchain more than once.",
1727 ))(info);
1728 }
1729
1730 pub fn record(self, cmd: vk::CommandBuffer, swapchain_index: usize) {
1732 (self.recorder)(cmd, swapchain_index);
1733 }
1734
1735 pub fn swapchain_recreate_required(&self) -> bool {
1737 self.swapchain_recreate_required
1738 }
1739}
1740impl Default for EguiCommand {
1741 fn default() -> Self {
1742 Self {
1743 swapchain_updater: None,
1744 recorder: Box::new(|_, _| {}),
1745 swapchain_recreate_required: false,
1746 }
1747 }
1748}