When we use MTLBlitCommandEncoder.copy to copy from buffer to textures with specific size, we find that the texture content is corruppt. The specific rules we found are:
On Apple GPUs (reproduced on Apple M5, macOS 26.3 and iPhone 13 / A15), for ASTC textures uploaded to private storage via the blit encoder, the sampler / texel-fetch mis-addresses the tail of a mip level when ALL of the following hold:
- that level's texel width is an exact multiple of the 16 KB page width (32 blocks) — 128 texels for ASTC 4x4, 192 for 6x6, 256 for 8x8;
- the texture width is not divisible by 2^level (a partial block column exists in the chain);
- that level is taller than one page (>32 block rows).
The level's first 128 texel rows (first page row, 4x4) are always read correctly; everything beyond is mis-addressed. Reads landing on unmapped/invalid memory decode as opaque magenta (1,0,1); reads aliasing valid memory show wrong image content. This produced visible purple artifacts in a shipping game (impostor tree atlas, 514x1024 ASTC 4x4, mip2 bottom half).
The minimum reproduce code is:
The output is:
514x1024 blit(private) mip2: CORRUPTED (bottom of mip2 mis-addressed)
512x1024 blit(private) mip2: INTACT
514x1024 replaceRegion mip2: INTACT