FyroxEngine/Fyrox · warning

generate_mipmap: format is not filterable, skipping

Error message

generate_mipmap: format is not filterable, skipping

What it means

wgpu requires the texture format to be filterable to use a render-bundle-based mipmap generation (which samples with a filtering sampler). The wgpu backend checks is_filterable_format and skips mip generation for non-filterable formats, logging this warning.

Solutions

  1. Create the texture with a filterable format (e.g. rgba8unorm / bgra8unorm)
  2. Fill mip levels manually with a compute or blit path for non-filterable formats
  3. Skip mip generation for formats where mips are unnecessary

Example fix

// before
let texture = server.create_texture(TextureDescriptor { pixel_format: Some(PixelFormat::R8), .. });
texture.generate_mipmap(server);
// after
let texture = server.create_texture(TextureDescriptor { pixel_format: Some(PixelFormat::RGBA8), .. });
texture.generate_mipmap(server);
Defensive patterns

Strategy: validation

Validate before calling

// choose a filterable format up front
const FILTERABLE: [PixelFormat; 3] = [PixelFormat::RGBA8, PixelFormat::RGB8, PixelFormat::RG8];
debug_assert!(FILTERABLE.contains(&pixel_format), "generate_mipmap needs a filterable format");

Prevention

When it happens

Trigger: Calling Texture::generate_mipmap (server.generate_mipmap) on a texture whose wgpu format is not filterable (e.g. depth formats, pure storage formats like rgba8uint, compressed formats).

Common situations: Generating mips for a depth texture or an integer/unorm-snorm-unsupported format; porting GL code that assumed glGenerateMipmap works for any format.

Related errors


AI-assisted analysis of FyroxEngine/Fyrox@76c91aad8e (2026-09-10). Data as JSON: /api/errors/233801c80adf770a. Report an issue: GitHub.

Appendix: source

Thrown at fyrox-graphics-wgpu/src/server.rs:741

    }
    fn capabilities(&self) -> ServerCapabilities {
        let limits = self.state.device.limits();
        ServerCapabilities {
            max_uniform_buffer_binding_size: limits.max_uniform_buffer_binding_size as usize,
            uniform_buffer_offset_alignment: limits.min_uniform_buffer_offset_alignment as usize,
            max_lod_bias: 16.0,
        }
    }
    fn set_polygon_fill_mode(&self, _face: PolygonFace, mode: PolygonFillMode) {
        self.polygon_fill_mode.set(mode);
    }
    fn generate_mipmap(&self, texture: &GpuTexture) {
        let Some(wtex) = texture.as_any().downcast_ref::<WgpuTexture>() else {
            return;
        };
        let format = wtex.format();
        if !is_filterable_format(format) {
            Log::warn("generate_mipmap: format is not filterable, skipping");
            return;
        }

        let (width, height, _depth) = texture_size(texture.kind());
        let mip_count = wtex.wgpu_texture().mip_level_count();
        if mip_count <= 1 || width <= 1 || height <= 1 {
            return;
        }

        self.flush_active_pass();

        let shader = self.mipmap_shader.get_or_init(|| {
            self.state
                .device
                .create_shader_module(wgpu::ShaderModuleDescriptor {
                    label: Some("MipmapShader"),
                    source: wgpu::ShaderSource::Wgsl(MIPMAP_SHADER_SRC.into()),
                })

View on GitHub (pinned to 76c91aad8e)