#Confusing borrow checker errors with wgpu

4 messages · Page 1 of 1 (latest)

red anchor
#

So I've got a function that takes in a closure and is supposed to pass it a render pass for rendering, but the borrow checker isnt happy at all
I'm not sure I really understand why?

pub struct State {
    instance: wgpu::Instance,
    adapter: wgpu::Adapter,
    device: wgpu::Device,
    queue: wgpu::Queue,
}

impl State {
    /* ... */

    pub fn render(&self, output: wgpu::SurfaceTexture, f: impl FnOnce(&mut wgpu::RenderPass)) {
        let view = output
            .texture
            .create_view(&wgpu::TextureViewDescriptor::default());
        let mut encoder = self
            .device
            .create_command_encoder(&wgpu::CommandEncoderDescriptor {
                label: Some("Render Encoder"),
            });

        let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
            label: Some("Render Pass"),
            color_attachments: &[Some(wgpu::RenderPassColorAttachment {
                view: &view,
                resolve_target: None,
                ops: wgpu::Operations {
                    load: wgpu::LoadOp::Clear(wgpu::Color {
                        r: 0.05,
                        g: 0.0,
                        b: 0.1,
                        a: 0.7,
                    }),
                    store: true,
                },
            })],
            depth_stencil_attachment: None,
        });

        f(&mut render_pass);

        drop(render_pass);

        self.queue.submit(std::iter::once(encoder.finish()));
        output.present();
    }
// place that actually calls State::render
pub async fn run(
    state: Arc<Mutex<State>>,
    mut event_recv: UnboundedReceiver<Event<'static, Message>>,
    mut writer: impl tokio::io::AsyncWriteExt + Unpin,
) -> ! {
    loop {
        // Process multiple events at a time in case they have been sent in rapid fire
        let mut events = vec![event_recv.recv().await.expect("sender is closed")];
        while let Ok(event) = event_recv.try_recv() {
            events.push(event);
        }
        let mut state = state.lock().await;
        let State {
            windows,
            wgpu_state,
        } = &mut *state;
        for event in events {
            match event {
              // lotsa matches
              Event::RedrawRequested(window_id) => {
                    let (_, window) = windows
                        .iter_mut()
                        .find(|(_, window)| window.window.id() == window_id)
                        .expect("window event received for nonexistent window");
                    let texture = window.surface.get_current_texture();

                    wgpu_state.render(texture, |render_pass| {
                        for sprite in window.sprites.values() {
                            let Some(ref texture) = sprite.image else { continue; };
                            render_pass.set_bind_group(0, texture.bind_group(), &[]);
                        }
                    });
             // more irrelevant code here

Actual error here:

error[E0499]: cannot borrow `*windows` as mutable more than once at a time
   --> ext/screen/src/event_loop.rs:144:39
    |
144 |                       let (_, window) = windows
    |  _______________________________________^
145 | |                         .iter_mut()
    | |                                   ^
    | |                                   |
    | |___________________________________`*windows` was mutably borrowed here in the previous iteration of the loop
    |                                     argument requires that `*windows` is borrowed for `'static`

I get errors like these on all match branches too?

steady vapor
#

the simplest thing to do is to structure your code so that the RenderPass is created by the code that uses it, concretely, instead of passing it out to a closure

red anchor
#

alright