The subscription feature doesn't work when integrating iced with existing application

Recently I am developing PDF Viewer on top of iced GUI and try to render PDF with vello. So I need to get following from wgpu and winit.

    window,
    device,
    queue,
    surface

I tried the integration example which shows how to do this job, but the subscription feature doesn’t work.

The example does something like this

use iced_winit::runtime::program;

  let state = program::State::new(
          program,
          viewport.logical_size(),
          &mut renderer,
          &mut debug,
      );

the iced_winit::runtime::program doesn’t have the subscription method, not the one from iced_winit crate, so no executor exists, that is why the subscription feature not work.

Any other way to do the integration without compromise please?

@hecrj Can I get a hand on this topic please?

The wgpu renderer has a draw_primitive method, it seems we can use it to render anything inside a customized widget, nice !

The primitive can’t be used this way, failed with following code.


impl PdfPrimitive
{
    pub fn new() -> Self
    {
        let render_params = vello::RenderParams {
            base_color: vello::peniko::Color::BLACK,
            width,
            height,
            antialiasing_method: vello::AaConfig::Area,
        };

        Self {
            render_params
        }
    }
}

impl iced_wgpu::Primitive for PdfPrimitive
{
    fn prepare(
        &self,
        device: &wgpu::Device,
        queue: &wgpu::Queue,
        format: wgpu::TextureFormat,
        storage: &mut iced_wgpu::primitive::Storage,
        bounds: &Rectangle,
        viewport: &iced::graphics::Viewport,
    )
    {
        // 1. Unable to save renderer variable  to self for it is not mutable
        // 2. also  the vello Renderer doesn't fulfill the  
        // this constraint:    pub trait Primitive: Debug + Send + Sync + 'static,
       let renderer = vello::Renderer::new(
            device,
            RendererOptions {
                surface_format: None,
                use_cpu: false,
                num_init_threads: NonZeroUsize::new(1),
                antialiasing_support: vello::AaSupport::area_only(),
            },
        ).ok();
    }

    fn render(
        &self,
        encoder: &mut wgpu::CommandEncoder,
        storage: &Storage,
        target: &wgpu::TextureView,
        clip_bounds: &Rectangle<u32>,
    ) {
        // the VelloBackend needs to mutate its argument, but  self is not mutable
        // maybe I can use Refcell
        let mut backend: VelloBackend<'_> = VelloBackend::new(&mut self.cache);

        let resolver = self.file.resolver();

        render_page(&mut backend, &resolver, &page, Transform2F::default()).ok()?;

        let scene = backend.finish();

        let mut render_pass = encoder.begin_render_pass(
            &wgpu::RenderPassDescriptor {
                label: Some("iced_wgpu render pass"),
                color_attachments: &[Some(wgpu::RenderPassColorAttachment {
                    view: frame,
                    resolve_target: None,
                    ops: wgpu::Operations {
                        load: match clear_color {
                            Some(background_color) => wgpu::LoadOp::Clear({
                                let [r, g, b, a] =
                                    graphics::color::pack(background_color)
                                        .components();

                                wgpu::Color {
                                    r: f64::from(r),
                                    g: f64::from(g),
                                    b: f64::from(b),
                                    a: f64::from(a),
                                }
                            }),
                            None => wgpu::LoadOp::Load,
                        },
                        store: wgpu::StoreOp::Store,
                    },
                })],
                depth_stencil_attachment: None,
                timestamp_writes: None,
                occlusion_query_set: None,
            },
        );
        render_pass.set_scissor_rect(clip_bounds.x, clip_bounds.y, clip_bounds.width, clip_bounds.height);

        // Unable to get queue and device, because the prepare method is not mutable

        if let Some(renderer) = self.renderer.as_mut() {
            renderer
                .render_to_texture(device, queue, &scene, &target, &self.render_params)
                .or_else(|_| bail!("Got non-Send/Sync error from rendering"))?;
        }
    }
}