gfx-rs/wgpu · error

MESH_SHADER feature must be enabled to call…

Error message

MESH_SHADER feature must be enabled to call create_mesh_pipeline

What it means

create_mesh_pipeline is unconditionally unimplemented in the web backend: any call panics stating the MESH_SHADER feature must be enabled. Browser WebGPU has no mesh-shader pipeline support, so the entry point exists only to satisfy the trait and can never succeed on this backend.

Solutions

  1. Check whether the backend supports mesh shaders (e.g. adapter features / cfg!(target_arch = "wasm32")) before creating a mesh pipeline, and fall back to a vertex/fragment pipeline on web.
  2. Keep mesh-shader paths behind a feature flag disabled for wasm builds.
  3. Implement a traditional vertex-buffer-based equivalent pipeline for web targets.

Example fix

// before
let pipeline = device.create_mesh_pipeline(&mesh_desc); // panics on web
// after
let pipeline = if cfg!(target_arch = "wasm32") { device.create_render_pipeline(&vert_frag_desc) } else { device.create_mesh_pipeline(&mesh_desc) };
Defensive patterns

Strategy: fallback

Validate before calling

if cfg!(target_arch = "wasm32") {
    return create_standard_render_pipeline(...); // mesh pipelines never available on web
}

Type guard

fn supports_mesh_pipelines(backend_is_web: bool) -> bool {
    !backend_is_web
}

Prevention

When it happens

Trigger: Calling device.create_mesh_pipeline with any descriptor on the web (wasm32/browser) backend, regardless of requested features.

Common situations: Shared render-path code that builds mesh shader pipelines (task/mesh stages) on native (e.g. Vulkan/DX12) also running on web; feature detection missing before choosing a mesh-based render path.

Related errors


AI-assisted analysis of gfx-rs/wgpu@3e11ff59bf (2026-09-03). Data as JSON: /api/errors/dbb5b253d3068d86. Report an issue: GitHub.

Appendix: source

Thrown at wgpu/src/backend/webgpu.rs:2504

        mapped_desc.set_multisample(&mapped_multisample);

        let mapped_primitive = map_primitive_state(&desc.primitive);
        mapped_desc.set_primitive(&mapped_primitive);

        let render_pipeline = self.inner.create_render_pipeline(&mapped_desc).unwrap();

        WebRenderPipeline {
            inner: render_pipeline,
            ident: crate::cmp::Identifier::create(),
        }
        .into()
    }

    fn create_mesh_pipeline(
        &self,
        _desc: &crate::MeshPipelineDescriptor<'_>,
    ) -> dispatch::DispatchRenderPipeline {
        panic!("MESH_SHADER feature must be enabled to call create_mesh_pipeline")
    }

    fn create_compute_pipeline(
        &self,
        desc: &crate::ComputePipelineDescriptor<'_>,
    ) -> dispatch::DispatchComputePipeline {
        let shader_module = desc.module.inner.as_webgpu();
        let mapped_compute_stage = webgpu_sys::GpuProgrammableStage::new(&shader_module.module);
        insert_constants_map(&mapped_compute_stage, desc.compilation_options.constants);
        if let Some(ep) = desc.entry_point {
            mapped_compute_stage.set_entry_point(ep);
        }
        let mapped_desc = match desc.layout {
            Some(layout) => webgpu_sys::GpuComputePipelineDescriptor::new(
                &layout.inner.as_webgpu().inner,
                &mapped_compute_stage,
            ),
            None => webgpu_sys::GpuComputePipelineDescriptor::new_with_gpu_auto_layout_mode(

View on GitHub (pinned to 3e11ff59bf)