Quick answer: Use ASTC or ETC2 compression supported by your minimum Android SDK. Generate mipmaps. Sample with explicit LOD on weak GPUs.

A terrain shader uses a Texture2DArray for 8 ground layer textures. On editor and high-end Android, renders fine. On older Android (Adreno 5xx), the lowest slice reads black, breaking the terrain.

Check Format Support

Debug.Log($"Format: {arr.graphicsFormat}");
Debug.Log($"Supports sampling: {SystemInfo.IsFormatSupported(arr.graphicsFormat, FormatUsage.Sample)}");

Some GPUs report supported but have driver bugs at runtime. Test on actual hardware.

Format Choice

For Android:

Import Settings: Default platform uses BC; Android override to ETC2_RGBA8 for safety.

Mipmaps Required

Some sampler implementations on mobile return zero when sampling a mip level that doesn’t exist. Set Generate Mip Maps on import, or build the array with mipmaps in code:

arr = new Texture2DArray(1024, 1024, slices, TextureFormat.ETC2_RGBA8, true);

Explicit LOD in Shader

Force a known mip on shaky drivers:

float4 col = SAMPLE_TEXTURE2D_ARRAY_LOD(_TerrainArray, sampler_TerrainArray, float3(uv, slice), 0);

Bypasses derivative-based LOD selection that some drivers mishandle for array textures.

Frame Debugger Inspection

Window → Analysis → Frame Debugger on device. Step to the draw call; inspect the Texture2DArray binding. Verify all slices have data — not just slice 0 black.

Verifying

Deploy to a low-end Android device. Terrain renders with all 8 layers visible. No black areas. Cross-test on iOS and high-end Android to ensure no regressions.

“Mobile GPU drivers vary. Standard formats, mipmaps, explicit LOD: three tools that fix most array-texture bugs.”

For wide device support, ETC2 with mips on Android baselined to API level 24 covers ~98% of active phones. Test on Mali 4xx/6xx and Adreno 5xx—those expose driver quirks fastest.