@@ -316,9 +316,22 @@ export const getGPUTier = async ({
316316 const blocklistedModel : string | undefined = BLOCKLISTED_GPUS . find (
317317 ( blocklistedModel ) => renderer ! . includes ( blocklistedModel )
318318 ) ;
319- return blocklistedModel
320- ? toResult ( 0 , 'BLOCKLISTED' , blocklistedModel )
321- : toResult ( 1 , 'FALLBACK' , `${ renderer } (${ rawRenderer } )` ) ;
319+ if ( blocklistedModel ) return toResult ( 0 , 'BLOCKLISTED' , blocklistedModel ) ;
320+
321+ // Apple Silicon on desktop Safari: the renderer string is the generic
322+ // "Apple GPU" and Safari reports identical WebGL capabilities across
323+ // M1–M5 (verified empirically on M1 Max / M2 / M4), so no web-facing
324+ // signal can identify the specific chip. The floor of the M-series
325+ // (base M1) sustains 60fps in our benchmark scene, which maps to the
326+ // top bin under the default `desktopTiers: [0, 15, 30, 60]` — so
327+ // tier 3 is a true lower bound for every Apple Silicon Mac, not a
328+ // guess. iPhone/iPad take an earlier path (deobfuscateAppleGPU fans
329+ // out to chip candidates), so this only fires on desktop.
330+ if ( ! isMobile && renderer === 'apple gpu' ) {
331+ return toResult ( 3 , 'FALLBACK' , 'apple gpu' , 60 ) ;
332+ }
333+
334+ return toResult ( 1 , 'FALLBACK' , `${ renderer } (${ rawRenderer } )` ) ;
322335 }
323336
324337 const [ , fps , model , device ] = results [ 0 ] ;
0 commit comments