# \[webGPU\] Created a RawTexture2DArray and only accessed the mip 0 layer

**URL:** <https://forum.babylonjs.com/t/webgpu-created-a-rawtexture2darray-and-only-accessed-the-mip-0-layer/64349>\
**Category:** Bugs\
**Tags:** material\
**Created:** [October 19, 2026, 10:07am UTC](https://forum.babylonjs.com/t/webgpu-created-a-rawtexture2darray-and-only-accessed-the-mip-0-layer/64349 "2026-10-19T10:07:50Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![John-D-a-i](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/john-d-a-i/32/52177_2.png) [@John-D-a-i](https://forum.babylonjs.com/u/John-D-a-i)\
**Post date:** [October 19, 2026, 10:07am UTC](https://forum.babylonjs.com/t/webgpu-created-a-rawtexture2darray-and-only-accessed-the-mip-0-layer/64349/1 "2026-10-19T10:07:50Z")

</div>

![image](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/c/6/c615496e0991673b34dec7f4859d26f3a69602f3.png)

 ![6ae4303a-3791-4079-8f7a-860c04f8fcb7](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/8/e/8e7263444c79e31b4870cbbc793ebdad7443fd41.png)

The WebGPU engine uses CreateTexture2DArrayFromImageUrlsAsync and the result is “Layer 0 is normal, while layers with index \> 0 are blank”.

The code is located in thinWebGPUEngine.js: The third parameter is faceIndex (which is the layer in the array texture), and it is hardcoded as 0 here.

```javascript
else if (texture._source === 3 /* Raw */ || texture._source === 11 /* Raw2DArray */) {
    this._textureHelper.generateMipmaps(gpuHardwareTexture, texture.mipLevelCount, 0, commandEncoder);
}

```

## 

CreateTexture2DArrayFromImageUrlsAsync has the default samplingMode set to TRILINEAR, and for a 512×512 size, it results in 10 levels of mip mapping:

Layer 0: Mip 0 is the one we uploaded (the generation is triggered once after all layers are uploaded), and mip 1 to 9 have also been generated → normal

Layers 1+ : Mip 1 to 9 were never generated. When creating the WebGPU texture, the texture is initialized to zero → sampling results in all zeros, alpha = 0 → mix(baseRgb, texColor.rgb, 0) retains the base color → the entire image disappears and this explains a phenomenon that should have been obvious: When the camera is moved closer and the parking space covers the entire screen, the second image suddenly appears (at this time, the sampling falls on mip 0). If the layer index itself is incorrect, there will definitely not be this “image appears only when viewing from a certain distance” behavior.

By the way, the path taken by WebGL2 is gl.generateMipmap(TEXTURE\_2D\_ARRAY), which by the specification will overwrite all layers, and there is no such proble

Temporary solution

```javascript
export function generateAllLayerMipmaps(scene: Scene, atlas: RawTexture2DArray): number {
  const engine = scene.getEngine() as unknown as {
    _textureHelper?: {
      generateMipmaps(hardwareTexture: unknown, mipLevelCount: number, faceIndex: number, commandEncoder?: unknown): void
    }
  }
  const internal = (
    atlas as unknown as {
      _texture?: { mipLevelCount: number; _hardwareTexture?: unknown }
    }
  )._texture

  const helper = engine._textureHelper
  const hardwareTexture = internal?._hardwareTexture
  const mipLevelCount = internal?.mipLevelCount ?? 1
  if (!helper || !hardwareTexture || mipLevelCount <= 1) return 0

  /
  for (let layer = 0; layer < atlas.depth; layer++) {
    helper.generateMipmaps(hardwareTexture, mipLevelCount, layer)
  }
  return atlas.depth
}

```

use

```javascript
 const textureArray = await CreateTexture2DArrayFromImageUrlsAsync(scene, ['img1.png',...])
      console.info(textureArray.depth)
      generateAllLayerMipmaps(scene, textureArray)

```

---

<div class="post-metadata">

**Author:** ![ctabone](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/ctabone/32/52182_2.png) [@ctabone](https://forum.babylonjs.com/u/ctabone)\
**Post date:** [October 19, 2026, 1:22pm UTC](https://forum.babylonjs.com/t/webgpu-created-a-rawtexture2darray-and-only-accessed-the-mip-0-layer/64349/2 "2026-10-19T13:22:11Z")

</div>

Confirming this, we hit the same bug independently. It isn’t limited to `CreateTexture2DArrayFromImageUrlsAsync`: a plain `new RawTexture2DArray(..., generateMipMaps: true, ...)` does the same on WebGPU. Only layer 0 gets a mip chain, and layers 1+ are black (all zeros) from mip 1 down. WebGL2 is fine.

In our game, a terrain shader samples a 2D-array of ground textures, and every layer except the first turned black a few metres from the camera.

Minimal repro, no image files needed (paste into the Playground with the WebGPU engine). Each layer is a solid colour, and we sample layer 1 at mip 3:

```js
const createScene = () => {
  const scene = new BABYLON.Scene(engine);
  const camera = new BABYLON.ArcRotateCamera("c", -Math.PI / 2, Math.PI / 2, 40, BABYLON.Vector3.Zero(), scene);
  camera.attachControl(canvas, true);
  // 3 layers, 256x256: red, green, blue.
  const size = 256, layers = 3, data = new Uint8Array(size * size * 4 * layers);
  for (let l = 0; l < layers; l++) for (let i = 0; i < size * size; i++)
    data.set([l === 0 ? 255 : 0, l === 1 ? 255 : 0, l === 2 ? 255 : 0, 255], (l * size * size + i) * 4);
  const arr = new BABYLON.RawTexture2DArray(data, size, size, layers, BABYLON.Constants.TEXTUREFORMAT_RGBA, scene,
    true /* generateMipMaps */, false, BABYLON.Texture.TRILINEAR_SAMPLINGMODE);
  BABYLON.Effect.ShadersStore.arrVertexShader = `precision highp float; attribute vec3 position; attribute vec2 uv;
    uniform mat4 worldViewProjection; varying vec2 vUV;
    void main() { vUV = uv; gl_Position = worldViewProjection * vec4(position, 1.0); }`;
  BABYLON.Effect.ShadersStore.arrFragmentShader = `precision highp float; precision highp sampler2DArray;
    uniform sampler2DArray arr; varying vec2 vUV;
    void main() { gl_FragColor = textureLod(arr, vec3(vUV, 1.0), 3.0); }`; // layer 1, mip 3
  const mat = new BABYLON.ShaderMaterial("m", scene, "arr", { attributes: ["position", "uv"], uniforms: ["worldViewProjection"], samplers: ["arr"] });
  mat.setTexture("arr", arr);
  BABYLON.MeshBuilder.CreatePlane("p", { size: 10 }, scene).material = mat;
  return scene;
};

```

- **Expected (and on WebGL2):** a green plane. Centre pixel `[0, 255, 0]`.
- **WebGPU:** a black plane. Centre pixel `[0, 0, 0]`. Sampling layer 0 at mip 3 gives red as expected.

We measured this on 9.12.0 (Chrome, Dawn/Vulkan, Intel Iris Xe). The same lines are unchanged in the 9.31.0 npm package and on master. #18941 recently added a 3D-texture branch to `_generateMipmaps`, but the `Raw2DArray` branch still passes layer `0`.

A possible fix in `ThinWebGPUEngine._generateMipmaps`, looping layers the way `generateCubeMipmaps` loops faces:

```ts
} else if (texture._source === InternalTextureSource.Raw2DArray) {
    for (let layer = 0; layer < texture.depth; ++layer) {
        this._textureHelper.generateMipmaps(gpuHardwareTexture, texture.mipLevelCount, layer, commandEncoder);
    }
} else if (texture._source === InternalTextureSource.Raw) {
    this._textureHelper.generateMipmaps(gpuHardwareTexture, texture.mipLevelCount, 0, commandEncoder);
}

```

Until then, we use a workaround like @John-D-a-i’s: wrap `engine._generateMipmaps` so a `Raw2DArray` texture also builds layers 1..depth-1. That works fine.

---

<div class="post-metadata">

**Author:** ![AlitarSemiramis](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/alitarsemiramis/32/49920_2.png) [@AlitarSemiramis](https://forum.babylonjs.com/u/AlitarSemiramis)\
**Post date:** [October 19, 2026, 4:20pm UTC](https://forum.babylonjs.com/t/webgpu-created-a-rawtexture2darray-and-only-accessed-the-mip-0-layer/64349/3 "2026-10-19T16:20:09Z")

</div>

I’ll take a look at this, thanks for reporting!

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [October 19, 2026, 4:26pm UTC](https://forum.babylonjs.com/t/webgpu-created-a-rawtexture2darray-and-only-accessed-the-mip-0-layer/64349/4 "2026-10-19T16:26:04Z")

</div>

Thanks for the detailed report and repro! You’re right: the WebGPU path was only generating mipmaps for layer 0, leaving the higher mip levels of the other layers empty.

I’ve opened a fix here: [PR #19009](https://github.com/BabylonJS/Babylon.js/pull/19009). It generates mipmaps for every layer while preserving the configured mip count, covering both direct `RawTexture2DArray` usage and `CreateTexture2DArrayFromImageUrlsAsync`.
