comfy_wgpu/
egui_integration.rs

1use egui::ClippedPrimitive;
2
3pub struct EguiRenderRoutine {
4    pub render_pass: egui_wgpu::Renderer,
5    pub screen_descriptor: egui_wgpu::ScreenDescriptor,
6    #[allow(dead_code)]
7    textures_to_free: Vec<egui::TextureId>,
8}
9
10impl EguiRenderRoutine {
11    /// Creates a new render routine to render a egui UI.
12    ///
13    /// Egui will always output gamma-encoded color. It will determine if to do
14    /// this in the shader manually based on the output format.
15    pub fn new(
16        device: &wgpu::Device,
17        surface_format: wgpu::TextureFormat,
18        samples: u32,
19        width: u32,
20        height: u32,
21        scale_factor: f32,
22    ) -> Self {
23        let render_pass =
24            egui_wgpu::Renderer::new(device, surface_format, None, samples);
25
26        Self {
27            render_pass,
28            screen_descriptor: egui_wgpu::ScreenDescriptor {
29                size_in_pixels: [width, height],
30                pixels_per_point: scale_factor,
31            },
32            textures_to_free: Vec::new(),
33        }
34    }
35
36    pub fn resize(
37        &mut self,
38        new_width: u32,
39        new_height: u32,
40        new_scale_factor: f32,
41    ) {
42        self.screen_descriptor = egui_wgpu::ScreenDescriptor {
43            size_in_pixels: [new_width, new_height],
44            pixels_per_point: new_scale_factor,
45        };
46    }
47
48    pub fn end_frame_and_render(
49        &mut self,
50        ctx: &egui::Context,
51        device: &wgpu::Device,
52        queue: &wgpu::Queue,
53        encoder: &mut wgpu::CommandEncoder,
54        pixels_per_point: f32,
55        // view: &wgpu::TextureView,
56        // render_pass: &'a mut wgpu::RenderPass<'a>,
57    ) -> Vec<ClippedPrimitive> {
58        let egui::FullOutput { shapes, textures_delta, .. } = ctx.end_frame();
59
60        let paint_jobs = ctx.tessellate(shapes, pixels_per_point);
61
62        for id in textures_delta.free {
63            self.render_pass.free_texture(&id);
64        }
65
66        for (id, image_delta) in textures_delta.set {
67            self.render_pass.update_texture(device, queue, id, &image_delta);
68        }
69
70        self.render_pass.update_buffers(
71            device,
72            queue,
73            encoder,
74            &paint_jobs,
75            &self.screen_descriptor,
76        );
77
78        paint_jobs
79        // self.render_pass.execute(
80        //     encoder,
81        //     view,
82        //     &paint_jobs,
83        //     &self.screen_descriptor,
84        //     None,
85        // );
86    }
87
88    // pub fn add_to_graph<'node>(
89    //     &'node mut self,
90    //     graph: &mut RenderGraph<'node>,
91    //     mut input: Input<'node>,
92    //     output: RenderTargetHandle,
93    // ) {
94    //     let mut builder = graph.add_node("egui");
95    //
96    //     let output_handle = builder.add_render_target_output(output);
97    //
98    //     let rpass_handle = builder.add_renderpass(RenderPassTargets {
99    //         targets: vec![RenderPassTarget {
100    //             color: output_handle,
101    //             clear: Color::BLACK,
102    //             resolve: None,
103    //         }],
104    //         depth_stencil: None,
105    //     });
106    //
107    //     // We can't free textures directly after the call to `execute_with_renderpass` as it freezes
108    //     // the lifetime of `self` for the remainder of the closure. so we instead buffer the textures
109    //     // to free for a frame so we can clean them up before the next call.
110    //     let textures_to_free = mem::replace(&mut self.textures_to_free, mem::take(&mut input.textures_delta.free));
111    //     let pt_handle = builder.passthrough_ref_mut(self);
112    //
113    //     builder.build(move |pt, renderer, encoder_or_pass, _temps, _ready, _graph_data| {
114    //         let this = pt.get_mut(pt_handle);
115    //         let rpass = encoder_or_pass.get_rpass(rpass_handle);
116    //
117    //         for tex in textures_to_free {
118    //             this.internal.free_texture(&tex);
119    //         }
120    //         for (id, image_delta) in input.textures_delta.set {
121    //             this.internal
122    //                 .update_texture(&renderer.device, &renderer.queue, id, &image_delta)
123    //         }
124    //
125    //         this.internal.update_buffers(
126    //             &renderer.device,
127    //             &renderer.queue,
128    //             input.paint_jobs,
129    //             &this.screen_descriptor,
130    //         );
131    //
132    //         this.internal
133    //             .execute_with_renderpass(rpass, input.paint_jobs, &this.screen_descriptor);
134    //     });
135    // }
136}