gfx-rs/wgpu · error

MESH_SHADER feature must be enabled to call draw_mesh_tasks

Error message

MESH_SHADER feature must be enabled to call draw_mesh_tasks

What it means

Mesh shaders are not part of the WebGPU API, so the WebGPU backend's RenderPassEncoder::draw_mesh_tasks is unimplemented and panics. Mesh-task drawing requires the MESH_SHADER feature on a native backend only.

Source

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

                instances.end - instances.start,
                vertices.start,
                instances.start,
            );
    }

    fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {
        self.inner
            .draw_indexed_with_instance_count_and_first_index_and_base_vertex_and_first_instance(
                indices.end - indices.start,
                instances.end - instances.start,
                indices.start,
                base_vertex,
                instances.start,
            )
    }

    fn draw_mesh_tasks(&mut self, _group_count_x: u32, _group_count_y: u32, _group_count_z: u32) {
        panic!("MESH_SHADER feature must be enabled to call draw_mesh_tasks")
    }

    fn draw_indirect(
        &mut self,
        indirect_buffer: &dispatch::DispatchBuffer,
        indirect_offset: crate::BufferAddress,
    ) {
        let buffer = indirect_buffer.as_webgpu();
        self.inner
            .draw_indirect_with_f64(&buffer.inner, indirect_offset as f64);
    }

    fn draw_indexed_indirect(
        &mut self,
        indirect_buffer: &dispatch::DispatchBuffer,
        indirect_offset: crate::BufferAddress,
    ) {
        let buffer = indirect_buffer.as_webgpu();

View on GitHub (pinned to 3e11ff59bf)

Solutions

  1. Gate draw_mesh_tasks behind Features::MESH_SHADER AND a non-WebGPU backend check.
  2. Provide a traditional vertex/fragment pipeline fallback for unsupported backends.
  3. Skip mesh-shader-only passes entirely when unsupported.
  4. Check device features at startup and refuse mesh-shader workloads on incompatible adapters.

Example fix

// before
render_pass.draw_mesh_tasks(1, 1, 1);
// after
if mesh_shader_supported {
    render_pass.draw_mesh_tasks(1, 1, 1);
} else {
    render_pass.draw(0..vertex_count, 0..1);
}
Defensive patterns

Strategy: validation

Validate before calling

let mesh_ok = device.features().contains(Features::MESH_SHADER) && !is_webgpu_backend;
if mesh_ok { render_pass.draw_mesh_tasks(1, 1, 1); } else { render_pass.draw(0..n, 0..1); }

Type guard

fn supports_mesh_shader(f: Features, b: Backend) -> bool {
    f.contains(Features::MESH_SHADER) && b != Backend::Browser
}

Prevention

When it happens

Trigger: Calling render_pass.draw_mesh_tasks(x, y, z) on a pass running via the webgpu backend, or on any backend without Features::MESH_SHADER enabled.

Common situations: Mesh/task pipeline rendering compiled to wasm; feature gates that checked only the device feature but not the backend; experimental mesh-shader demos ported to the browser.

Related errors


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