Data corruption when using MTLBlitCommandEncoder.copy from buffer to texture

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:

  1. 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;
  2. the texture width is not divisible by 2^level (a partial block column exists in the chain);
  3. 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

Thanks for the investigation. If you haven’t already, please file a report through Feedback Assistant, including your repro program. If you’ve already filed, can you please share the FB number here?

Data corruption when using MTLBlitCommandEncoder.copy from buffer to texture
 
 
Q