{"record":{"id":"e5fca4c5741e26a1","repo":"BabylonJS/Babylon.js","slug":"unable-to-create-multi-sampled-framebuffer-e5fca4","errorCode":null,"errorMessage":"Unable to create multi sampled framebuffer","messagePattern":"Unable to create multi sampled framebuffer","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/dev/core/src/Engines/Extensions/engine.renderTarget.pure.ts","lineNumber":222,"sourceCode":"        // Dispose previous render buffers\r\n        if (rtWrapper._depthStencilBuffer) {\r\n            gl.deleteRenderbuffer(rtWrapper._depthStencilBuffer);\r\n            rtWrapper._depthStencilBuffer = null;\r\n        }\r\n\r\n        if (rtWrapper._MSAAFramebuffer) {\r\n            gl.deleteFramebuffer(rtWrapper._MSAAFramebuffer);\r\n            rtWrapper._MSAAFramebuffer = null;\r\n        }\r\n\r\n        const hardwareTexture = rtWrapper.texture?._hardwareTexture as Nullable<WebGLHardwareTexture>;\r\n        hardwareTexture?.releaseMSAARenderBuffers();\r\n\r\n        if (rtWrapper.texture && samples > 1 && typeof gl.renderbufferStorageMultisample === \"function\") {\r\n            const framebuffer = gl.createFramebuffer();\r\n\r\n            if (!framebuffer) {\r\n                throw new Error(\"Unable to create multi sampled framebuffer\");\r\n            }\r\n\r\n            rtWrapper._MSAAFramebuffer = framebuffer;\r\n            this._bindUnboundFramebuffer(rtWrapper._MSAAFramebuffer);\r\n\r\n            const colorRenderbuffer = this._createRenderBuffer(\r\n                rtWrapper.texture.width,\r\n                rtWrapper.texture.height,\r\n                samples,\r\n                -1 /* not used */,\r\n                this._getRGBABufferInternalSizedFormat(rtWrapper.texture.type, rtWrapper.texture.format, rtWrapper.texture._useSRGBBuffer),\r\n                gl.COLOR_ATTACHMENT0,\r\n                false\r\n            );\r\n\r\n            if (!colorRenderbuffer) {\r\n                throw new Error(\"Unable to create multi sampled framebuffer\");\r\n            }\r","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/core/src/Engines/Extensions/engine.renderTarget.pure.ts#L204-L240","documentation":"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.","triggerScenarios":"engine.createRenderTargetTexture / RenderTargetTexture creation or resize with samples > 1 where gl.createFramebuffer() returns null (context loss, resource exhaustion).","commonSituations":"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.","solutions":["Lower samples (2 or 1) on the render target","Check for and recover from context loss (webglcontextlost/webglcontextrestored)","Dispose unused render targets to free framebuffer objects","Update GPU drivers; verify on other hardware","Try-catch creation and rebuild the render target without MSAA"],"exampleFix":"// before\nconst rt = engine.createRenderTargetTexture(size, { samples: 4 });\n// after\nlet rt;\ntry {\n  rt = engine.createRenderTargetTexture(size, { samples: 4 });\n} catch {\n  rt = engine.createRenderTargetTexture(size, {}); // no MSAA\n}","handlingStrategy":"try-catch","validationCode":"function msaaSupported(engine, samples) {\n  const gl = engine._gl;\n  if (!gl || typeof gl.renderbufferStorageMultisample !== 'function') return false;\n  return samples <= gl.getParameter(gl.MAX_SAMPLES);\n}","typeGuard":"function hasLiveContext(engine): boolean {\n  return !engine.isDisposed && !!(engine as any)._gl;\n}","tryCatchPattern":"try {\n  const rt = engine.createRenderTargetTexture(size, { samples: 4 });\n} catch (e) {\n  if (String(e?.message).includes('multi sampled framebuffer')) {\n    const rt = engine.createRenderTargetTexture(size, {}); // MSAA off\n  } else { throw e; }\n}","preventionTips":["Clamp samples to gl.MAX_SAMPLES","Recover render targets after context restore","Dispose stale render targets to avoid framebuffer exhaustion","Avoid repeated resize churn on MSAA targets","Validate MSAA on target hardware early"],"tags":["webgl","framebuffer","msaa","render-target"],"backgroundTag":"webgl-framebuffer-creation-failed","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}