egui_ash/
renderer.rs

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            // position
119            vk::VertexInputAttributeDescription::builder()
120                .binding(0)
121                .offset(0)
122                .location(0)
123                .format(vk::Format::R32G32_SFLOAT)
124                .build(),
125            // uv
126            vk::VertexInputAttributeDescription::builder()
127                .binding(0)
128                .offset(8)
129                .location(1)
130                .format(vk::Format::R32G32_SFLOAT)
131                .build(),
132            // color
133            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        // wait device idle
423        unsafe {
424            self.device
425                .device_wait_idle()
426                .expect("Failed to wait device idle.");
427        }
428
429        // cleanup framebuffers and others
430        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        // Create Framebuffers
471        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        // update self
484        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    // size for vertex buffer which egui-ash uses
504    fn vertex_buffer_size() -> u64 {
505        1024 * 1024 * 4
506    }
507
508    // size for index buffer which egui-ash uses
509    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                    // update textures
563                    managed_textures.update_textures(textures_delta);
564                    user_textures.update_textures();
565
566                    // get buffer ptr
567                    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                    // begin render pass
581                    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                    // bind resources
600                    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                    // render meshes
637                    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                        // map memory
707                        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                        // record draw commands
718                        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                    // end render pass
780                    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            // wait device idle
792            unsafe {
793                self.device
794                    .device_wait_idle()
795                    .expect("Failed to wait device idle")
796            };
797
798            // destroy state
799            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        // Extract pixel data from egui
895        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        // begin cmd
1039        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        // Transition texture image for transfer dst
1049        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        // texture is now in GPU memory, now we need to decide whether we should register it as new or update existing
1134
1135        if let Some(pos) = delta.pos {
1136            // Blit texture data to existing texture if delta pos exists (e.g. font changed)
1137            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                    // begin cmd buff
1151                    self.device
1152                        .begin_command_buffer(
1153                            cmd,
1154                            &vk::CommandBufferBeginInfo::builder()
1155                                .flags(vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT),
1156                        )
1157                        .unwrap();
1158
1159                    // Transition existing image for transfer dst
1160                    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                    // Transition new image for transfer src
1181                    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                    // Transition existing image for shader read
1246                    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                    // destroy texture_image and view
1282                    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            // Otherwise save the newly created texture
1291
1292            // update dsc set
1293            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            // destroy old texture
1323            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            // register new texture
1334            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        // cleanup
1342        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        // wait device idle
1378        unsafe {
1379            device
1380                .device_wait_idle()
1381                .expect("Failed to wait device idle")
1382        };
1383
1384        // destroy images
1385        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        // wait device idle
1682        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
1704/// struct to pass to `EguiCommand::update_swapchain` method.
1705pub 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
1712/// command recorder to record egui draw commands.
1713///
1714/// if you recreate swapchain, you must call `update_swapchain` method.
1715/// You also must call `update_swapchain` method when first time to record commands.
1716pub 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    /// You must call this method once when first time to record commands
1723    /// and when you recreate swapchain.
1724    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    /// record commands to command buffer.
1731    pub fn record(self, cmd: vk::CommandBuffer, swapchain_index: usize) {
1732        (self.recorder)(cmd, swapchain_index);
1733    }
1734
1735    /// Returns whether swapchain recreation is required.
1736    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}