CNA-PLAT-016: On Apple GPUs SamplerState.MipMapLevelOfDetailBias is refused by METAL below macOS/iOS 26, in builds against an older SDK and on devices that ignore it, and does not reach the GPU on FNA3D's Metal-backed driver
Evidence basis: source-verified at the pinned commit; recorded by CNA's own run (not repeated here); tests exist (not executed for this page). Claims on this page were checked by reading the CNA source at commit c1c316b9; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.
METAL throws NotSupportedException for a non-zero sampler LOD bias unless the OS and the build SDK are 26 or later and the device honours the bias; FNA3D on Apple hands the bias to SDL's Metal backend, which ignores it.
- Identifier
CNA-PLAT-016- Category
- Platform limitation
- Subsystem
- Graphics & renderers
- Status
- Open
- Verified against
- CNA
c1c316b9(c1c316b9c7a846ce8002809c151fcd1af14942c9) - Evidence basis
- Recorded by CNA: CNA's own recorded run, not repeated here
- Tests touching this area
- Yes: see Current tests
- Affected contract
- SamplerState.MipMapLevelOfDetailBias on the METAL renderer, and on the FNA3D renderer on macOS and iOS
Expected behaviour
XNA 4.0 applies SamplerState.MipMapLevelOfDetailBias on every device: a bias of +1 selects the next smaller mip level, and a game that sharpens or blurs textures with it gets the same mip selection everywhere.
Actual behaviour at TARGET
- METAL:
samplerForinMetalRenderer.mmmaps the bias ontoMTLSamplerDescriptor.lodBias, which exists only from macOS/iOS 26 and is compiled only when the build SDK declares it (CNA_METAL_SDK_HAS_SAMPLER_LOD_BIAS, AM4-099). A non-zero bias on an older OS, or from a build made with an older SDK, throwsSystem::NotSupportedException(‘needs macOS/iOS 26 and a build against their SDK’). Even then, the first non-zero bias runs a one-time probe (metalDeviceHonoursSamplerLodBias, AM4-296): CNA measured that the Apple Paravirtual device of the hosted macOS runners acceptslodBiasand ignores it, so on a device that ignores it the bias is refused the same way. A bias of 0 always works. - FNA3D on Apple: FNA3D selects its SDL_GPU driver, which runs on SDL's Metal backend; that backend ignores
mip_lod_bias, and FNA3D's MojoShader shaders have no other route for it, so the bias is accepted and has no effect.Fna3dRenderer::SamplerLodBiasReachesTheGpuEXT()(Fna3dRenderer.cpp, AM4-191) reports false on Apple for every driver but OpenGL; nothing is thrown.
CNA's own SDL_GPU renderer is not affected for stock effects, which carry the bias in their shaders (SDLGPU-121).
Source locations
modules/renderers/metal/src/MetalRenderer.mm— samplerFor: the macOS/iOS 26 and SDK guard and the device probe (metalDeviceHonoursSamplerLodBias) that refuse a non-zero biasmodules/renderers/fna3d/src/Fna3dRenderer.cpp— Fna3dRenderer::SamplerLodBiasReachesTheGpuEXT: false on Apple unless FNA3D runs its OpenGL driver; ApplySamplerMipState hands the bias to FNA3Ddocs/fx-compiled-effects.md— Sampler state that reaches the GPU: the per-backend MipMapLevelOfDetailBias rowdocs/metal-renderer.md— sampler LOD bias needs macOS/iOS 26 (AM4-034)docs/apple-platforms.md— macOS status table: LOD bias needs macOS/iOS 26 for METAL; SDL's Metal backend ignores mip_lod_biasplans/plan_apple_m4.md— AM4-034, AM4-099, AM4-191 and AM4-296: the guard, the SDK macro, FNA3D's report and the measured paravirtual devicemodules/graphics/examples/texture_filter_mip_contract_test.cpp— the shared mip contract accepts a Metal refusal of a non-zero bias and requires every other renderer to apply itmodules/renderers/fna3d/tests/CNA/Internal/Renderers/Fna3d/Fna3dCompiledEffectTests.cpp— the FNA3D sampler contract declares the bias unsupported where SamplerLodBiasReachesTheGpuEXT is false
Evidence
Read at c1c316b9: the Metal sampler cache and its probe, FNA3D's SamplerLodBiasReachesTheGpuEXT, the shared mip contract test and CNA's records; nothing was executed here. The behaviour on devices is CNA's own measurement: AM4-296 records a CNA-free probe on the hosted runner's Apple Paravirtual device that samples level 0 at a +1 and a +2 sampler bias while the shader's own bias selects levels 1 and 2, and a Mac mini M4 that honours it; AM4-191 records that FNA3D's SDL_GPU driver on Metal ignores the bias. The pre-26 refusal follows from the @available guard and the SDK macro; CNA notes it was not executed against a real pre-26 SDK. Related but older and outside Apple: MipMapLevelOfDetailBias has no OpenGL ES equivalent, so EasyGL's OPENGLES3 and WEBGL2 identities accept it without effect, as fx-compiled-effects.md documents.
Focused reproduction
No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.
Current tests
texture_filter_mip_contract_test.cpp draws one raw biased draw first and accepts a NotSupportedException on Metal only (any other renderer refusing fails); the FNA3D compiled-effect sampler contract passes SamplerLodBiasReachesTheGpuEXT() as its supportsLodBias option, so on Apple it skips the bias section. No test asserts the pre-26 refusal on a real older OS or SDK.
Regression test
The existing contract tests are the regression tests; what is missing is a run on macOS below 26 (or a build against an older SDK) that confirms the refusal, and, if FNA3D gains a shader route for the bias, removing the Apple exception from its sampler contract.
Blast radius
Games that set a non-zero MipMapLevelOfDetailBias: on METAL they get an exception on macOS/iOS below 26, from a build made with an older Xcode SDK, or on a GPU that ignores the bias (the hosted macOS CI runners); on FNA3D on Apple the textures are sampled as if the bias were 0. A bias of 0, every other sampler state, and the other renderers on Apple are unaffected.
Workaround
Keep the bias at 0 on Apple, or catch the exception and fall back; alternatively bias the mip level in the shader of a compiled effect, which on the device CNA measured is honoured where the sampler's bias is ignored. Build METAL with an Xcode that ships the macOS/iOS 26 SDK when the sampler bias is needed.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- Known issues
- Platform limitation index