Can't move out of shaders cause it's borrowed

fn new(w: Arc<Window>) -> Self {
        let size = w.inner_size();
        let inst = wgpu::Instance::new(wgpu::InstanceDescriptor {
            backends: wgpu::Backends::PRIMARY,
            ..Default::default()
        });
        let surf = unsafe {
            inst.create_surface_unsafe(SurfaceTargetUnsafe::from_window(w.as_ref()).unwrap())
        }
        .unwrap();
        let adapter = inst
            .request_adapter(&wgpu::RequestAdapterOptions {
                power_preference: wgpu::PowerPreference::HighPerformance,
                compatible_surface: Some(&surf),
                force_fallback_adapter: false,
            })
            .block_on();
        let adaptuw;
        if adapter.is_some() {
            adaptuw = unsafe { adapter.unwrap_unchecked() };
        } else {
            adaptuw = inst
                .enumerate_adapters(wgpu::Backends::PRIMARY)
                .into_iter()
                .filter(|adapter| {
                    // Check if this adapter supports our surface
                    adapter.is_surface_supported(&surf)
                })
                .next()
                .unwrap();
        }
        let (dev, q) = adaptuw
            .request_device(
                &wgpu::DeviceDescriptor {
                    required_features: wgpu::Features::empty(),
                    required_limits: wgpu::Limits::default(),
                    label: None,
                },
                None,
            )
            .block_on()
            .unwrap();
        let rpiplay = Arc::new(dev.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
            label: None,
            bind_group_layouts: &[],
            push_constant_ranges: &[],
        }));
        let surfcaps = surf.get_capabilities(&adaptuw);
        let surface_format = surfcaps
            .formats
            .iter()
            .filter(|f| f.is_srgb())
            .next()
            .unwrap_or(&surfcaps.formats[0]);
        let conf = wgpu::SurfaceConfiguration {
            usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
            format: *surface_format,
            width: size.width,
            height: size.height,
            present_mode: surfcaps.present_modes[0],
            alpha_mode: surfcaps.alpha_modes[0],
            view_formats: Vec::new(),
            desired_maximum_frame_latency: 2,
        };
        let shaders: Vec<ShaderModule> = vec![dev.create_shader_module(wgpu::include_wgsl!("shader.wgsl"))];
        let rpipdesc = wgpu::RenderPipelineDescriptor {
            label: None,
            layout: Some(&rpiplay.clone()),
            vertex: wgpu::VertexState {
                module: &shaders[0],
                entry_point: "vs_main", // 1.
                buffers: &[],           // 2.
                compilation_options: wgpu::PipelineCompilationOptions::default(),
            },
            fragment: Some(wgpu::FragmentState {
                // 3.
                module: &shaders[0],
                entry_point: "fs_main",
                targets: &[Some(wgpu::ColorTargetState {
                    // 4.
                    format: conf.format,
                    blend: Some(wgpu::BlendState::REPLACE),
                    write_mask: wgpu::ColorWrites::ALL,
                })],
                compilation_options: wgpu::PipelineCompilationOptions::default(),
            }),
            primitive: wgpu::PrimitiveState {
                topology: wgpu::PrimitiveTopology::TriangleList, // 1.
                strip_index_format: None,
                front_face: wgpu::FrontFace::Ccw, // 2.
                cull_mode: Some(wgpu::Face::Back),
                // Setting this to anything other than Fill requires Features::NON_FILL_POLYGON_MODE
                polygon_mode: wgpu::PolygonMode::Fill,
                // Requires Features::DEPTH_CLIP_CONTROL
                unclipped_depth: false,
                // Requires Features::CONSERVATIVE_RASTERIZATION
                conservative: false,
            },
            depth_stencil: None, // 1.
            multisample: wgpu::MultisampleState {
                count: 1,                         // 2.
                mask: !0,                         // 3.
                alpha_to_coverage_enabled: false, // 4.
            },
            multiview: None, // 5.
        };
        Self {
            surf,
            dev,
            q,
            conf,
            size,
            w,
            rpiplay,
            rpipdesc,
            shaders,
        }
    }

You have some labeled lines, did you mean to have more description of the problem?

In any case, the issue here is pretty simple: you're trying to return rpidesc which has references to the local shader (among others), which is not directly expressible in Rust for reasons that are a bit hard to explain quickly.

The short version is that you shouldn't try to keep these descriptor types (or any other types containing references) around, they're just for providing arguments to the create functions.

You can either create the pipeline immediately, or if you want to do it multiple times move the entire create with the descriptor into a method.

Will initialization each time be compiled away?

If you're creating pipelines often enough for this to matter you have much bigger issues than filling out a few hundred bytes! Pipeline creation is incredibly expensive, you should ideally be doing it a handful of times at startup, and it would be with different parameters each time.

I'm not, just want to be performant

If you have to do it once, you have to do it once, it doesn't really matter where it is.

If you're curious about this sort of thing, try out using compiler explorer to compare the code generated for different versions. It's a complicated tool, but much better than just trying to guess what the compiler will do!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.