BabylonJS/Babylon.js · error

Can't handle more than 8 attachments for a MRT in cache rend

Error message

Can't handle more than 8 attachments for a MRT in cache render pipeline!

What it means

WebGPUCacheRenderPipeline.setMRT enforces the WebGPU limit of 8 color attachments per render pass. Passing an InternalTexture array (or textureCount) larger than 8 throws, because the pipeline cache encodes at most 8 MRT attachments.

Source

Thrown at packages/dev/core/src/Engines/WebGPU/webgpuCacheRenderPipeline.ts:370

        (this.mrtAttachments as any) = attachments;
        let mask = 0;
        for (let i = 0; i < attachments.length; ++i) {
            if (attachments[i] !== 0) {
                mask += 1 << i;
            }
        }
        if (this._mrtEnabledMask !== mask) {
            this._mrtEnabledMask = mask;
            this._isDirty = true;
            this._stateDirtyLowestIndex = Math.min(this._stateDirtyLowestIndex, StatePosition.MRTAttachments);
        }
    }

    public setMRT(textureArray: InternalTexture[], textureCount?: number): void {
        textureCount = textureCount ?? textureArray.length;
        if (textureCount > 8) {
            // We only support 8 MRTs in WebGPU, so we throw an error if we try to set more than that.
            throw new Error("Can't handle more than 8 attachments for a MRT in cache render pipeline!");
        }
        (this.mrtTextureArray as any) = textureArray;
        (this.mrtTextureCount as any) = textureCount;

        // Since we need approximately 45 different values per texture format (see WebGPUTextureManager.renderableTextureFormatToIndex), we use 6 bits to encode a texture format,
        // which means we can encode 8 texture formats in 48 bits (a double can represent integers exactly up until 2^53, so 48 bits is ok).

        this._mrtEnabledMask = 0xffff; // all textures are enabled at start (meaning we can write to them). Calls to setMRTAttachments may disable some

        let mrtAttachments = 0;
        let mask = 0;

        for (let i = 0; i < textureCount; ++i) {
            const texture = textureArray[i];
            const gpuWrapper = texture?._hardwareTexture as Nullable<WebGPUHardwareTexture>;

            this._mrtFormats[i] = gpuWrapper?.format ?? this._webgpuColorFormat[0];

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Reduce the number of simultaneous render targets to at most 8 (merge/pack attachments, e.g. into RGBA channels).
  2. Split the rendering into multiple passes, writing a subset of targets per pass.
  3. Verify the textureCount argument; pass it explicitly only when it correctly equals the attachment count.

Example fix

// before
pipeline.setMRT([t0,t1,t2,t3,t4,t5,t6,t7,t8]); // 9 targets
// after
pipeline.setMRT([t0,t1,t2,t3,t4,t5,t6,t7]); // pack extra data or use a second pass
Defensive patterns

Strategy: validation

Validate before calling

if (textureArray.length > 8 || (textureCount ?? textureArray.length) > 8) {
  throw new RangeError('WebGPU supports at most 8 MRT attachments; reduce or pack render targets');
}
pipeline.setMRT(textureArray, textureCount);

Type guard

function fitsWebGPUMrt(textures: unknown[], count?: number): textures is BABYLON.InternalTexture[] {
  return textures.length <= 8 && (count ?? textures.length) <= 8;
}

Try / catch

try {
  pipeline.setMRT(textures, count);
} catch (e) {
  if (String(e.message).includes('more than 8 attachments')) {
    pipeline.setMRT(textures.slice(0, 8), 8); // render remaining targets in a second pass
  } else throw e;
}

Prevention

When it happens

Trigger: Calling setMRT with an array of more than 8 internal textures, or passing an explicit textureCount > 8, typically through engine device reset/pipeline setup paths that wire many render targets.

Common situations: Custom MRT setups with 9+ render targets (e.g. G-buffer with many attachments); porting a Vulkan/DirectX engine with higher MRT limits to WebGPU; miscomputed textureCount from a bad length.

Related errors


AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30). Data as JSON: /api/errors/d18b16faa639da40. Report an issue: GitHub.