BabylonJS/Babylon.js · error

Unable to create multi sampled framebuffer

Error message

Unable to create multi sampled framebuffer

What it means

When creating/updating a render target wrapper with samples > 1 (and WebGL2 renderbufferStorageMultisample available), the engine allocates an MSAA framebuffer via gl.createFramebuffer(). A null return triggers this error. It indicates the driver could not create the framebuffer object for the render target's MSAA resolve path.

Source

Thrown at packages/dev/core/src/Engines/Extensions/engine.renderTarget.pure.ts:222

        // Dispose previous render buffers
        if (rtWrapper._depthStencilBuffer) {
            gl.deleteRenderbuffer(rtWrapper._depthStencilBuffer);
            rtWrapper._depthStencilBuffer = null;
        }

        if (rtWrapper._MSAAFramebuffer) {
            gl.deleteFramebuffer(rtWrapper._MSAAFramebuffer);
            rtWrapper._MSAAFramebuffer = null;
        }

        const hardwareTexture = rtWrapper.texture?._hardwareTexture as Nullable<WebGLHardwareTexture>;
        hardwareTexture?.releaseMSAARenderBuffers();

        if (rtWrapper.texture && samples > 1 && typeof gl.renderbufferStorageMultisample === "function") {
            const framebuffer = gl.createFramebuffer();

            if (!framebuffer) {
                throw new Error("Unable to create multi sampled framebuffer");
            }

            rtWrapper._MSAAFramebuffer = framebuffer;
            this._bindUnboundFramebuffer(rtWrapper._MSAAFramebuffer);

            const colorRenderbuffer = this._createRenderBuffer(
                rtWrapper.texture.width,
                rtWrapper.texture.height,
                samples,
                -1 /* not used */,
                this._getRGBABufferInternalSizedFormat(rtWrapper.texture.type, rtWrapper.texture.format, rtWrapper.texture._useSRGBBuffer),
                gl.COLOR_ATTACHMENT0,
                false
            );

            if (!colorRenderbuffer) {
                throw new Error("Unable to create multi sampled framebuffer");
            }

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Lower samples (2 or 1) on the render target
  2. Check for and recover from context loss (webglcontextlost/webglcontextrestored)
  3. Dispose unused render targets to free framebuffer objects
  4. Update GPU drivers; verify on other hardware
  5. Try-catch creation and rebuild the render target without MSAA

Example fix

// before
const rt = engine.createRenderTargetTexture(size, { samples: 4 });
// after
let rt;
try {
  rt = engine.createRenderTargetTexture(size, { samples: 4 });
} catch {
  rt = engine.createRenderTargetTexture(size, {}); // no MSAA
}
Defensive patterns

Strategy: try-catch

Validate before calling

function msaaSupported(engine, samples) {
  const gl = engine._gl;
  if (!gl || typeof gl.renderbufferStorageMultisample !== 'function') return false;
  return samples <= gl.getParameter(gl.MAX_SAMPLES);
}

Type guard

function hasLiveContext(engine): boolean {
  return !engine.isDisposed && !!(engine as any)._gl;
}

Try / catch

try {
  const rt = engine.createRenderTargetTexture(size, { samples: 4 });
} catch (e) {
  if (String(e?.message).includes('multi sampled framebuffer')) {
    const rt = engine.createRenderTargetTexture(size, {}); // MSAA off
  } else { throw e; }
}

Prevention

When it happens

Trigger: engine.createRenderTargetTexture / RenderTargetTexture creation or resize with samples > 1 where gl.createFramebuffer() returns null (context loss, resource exhaustion).

Common situations: MSAA render targets (samples=4) created at startup on constrained GPUs; resizing render targets repeatedly leaking framebuffers; context lost mid-frame; old drivers with framebuffer allocation bugs.

Related errors


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