gfx-rs/wgpu · error

MESH_SHADER feature must be enabled to call multi_draw_mesh_

Error message

MESH_SHADER feature must be enabled to call multi_draw_mesh_tasks_indirect

What it means

The WebGPU backend cannot perform batched indirect mesh-task draws, so multi_draw_mesh_tasks_indirect panics unconditionally. Like the other mesh-task entry points it requires the MESH_SHADER feature on a native backend.

Source

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

        indirect_offset: crate::BufferAddress,
        count: u32,
    ) {
        let buffer = indirect_buffer.as_webgpu();

        for i in 0..count {
            let offset = indirect_offset + i as crate::BufferAddress * 20;
            self.inner
                .draw_indexed_indirect_with_f64(&buffer.inner, offset as f64);
        }
    }

    fn multi_draw_mesh_tasks_indirect(
        &mut self,
        _indirect_buffer: &dispatch::DispatchBuffer,
        _indirect_offset: crate::BufferAddress,
        _count: u32,
    ) {
        panic!("MESH_SHADER feature must be enabled to call multi_draw_mesh_tasks_indirect")
    }

    fn multi_draw_indirect_count(
        &mut self,
        _indirect_buffer: &dispatch::DispatchBuffer,
        _indirect_offset: crate::BufferAddress,
        _count_buffer: &dispatch::DispatchBuffer,
        _count_buffer_offset: crate::BufferAddress,
        _max_count: u32,
    ) {
        panic!(
            "MULTI_DRAW_INDIRECT_COUNT feature must be enabled to call multi_draw_indirect_count"
        )
    }

    fn multi_draw_indexed_indirect_count(
        &mut self,
        _indirect_buffer: &dispatch::DispatchBuffer,

View on GitHub (pinned to 3e11ff59bf)

Solutions

  1. Gate the call behind Features::MESH_SHADER and backend != WebGPU.
  2. Loop individual draw_mesh_tasks_indirect calls only on supporting backends, otherwise use a non-mesh fallback.
  3. Restructure GPU-driven rendering to a compute-generated indirect buffer consumed by draw_indirect on web.
  4. Resolve a rendering-path enum once at device creation and dispatch on it.

Example fix

// before
render_pass.multi_draw_mesh_tasks_indirect(&buf, 0, count);
// after
if mesh_shader_supported {
    render_pass.multi_draw_mesh_tasks_indirect(&buf, 0, count);
} else {
    for i in 0..count { render_pass.draw_indirect(&buf, i * stride); }
}
Defensive patterns

Strategy: validation

Validate before calling

if supports_mesh_shader(device.features(), backend) {
    render_pass.multi_draw_mesh_tasks_indirect(&buf, 0, count);
} else { /* fallback */ }

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.multi_draw_mesh_tasks_indirect(indirect_buffer, indirect_offset, count) on the webgpu backend, or on a backend lacking Features::MESH_SHADER.

Common situations: GPU-driven culling systems issuing many mesh-task draws from one buffer, ported to wasm; generic multi-draw dispatch shared across backends; benchmarks exercising all multi-draw variants on every backend.

Related errors


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