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

CNA snapshot c1c316b9  ·  Known Issues › Platform limitations  ·  source links pinned to c1c316b9

✓

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: samplerFor in MetalRenderer.mm maps the bias onto MTLSamplerDescriptor.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, throws System::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 accepts lodBias and 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

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.

The same subject is explained at several altitudes. These are the neighbouring pages at each one.