{"record":{"id":"f6214696e76ed9e9","repo":"BabylonJS/Babylon.js","slug":"updatewrappedwebgltexture-wrapped-texture-is-part","errorCode":null,"errorMessage":"updateWrappedWebGLTexture: wrapped texture is part of a multi render-target; not supported. Dispose and re-wrap.","messagePattern":"updateWrappedWebGLTexture: wrapped texture is part of a multi render-target; not supported\\. Dispose and re-wrap\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/dev/core/src/Engines/engine.pure.ts","lineNumber":826,"sourceCode":"     * render-target wrapper, or if the wrapper has a depth/stencil texture (these are not supported in this version;\r\n     * dispose and re-wrap).\r\n     * @param internalTexture defines the wrapped InternalTexture to repoint\r\n     * @param texture defines the new WebGL handle to wrap\r\n     */\r\n    public updateWrappedWebGLTexture(internalTexture: InternalTexture, texture: WebGLTexture): void {\r\n        if (internalTexture.source !== InternalTextureSource.External) {\r\n            throw new Error(\"updateWrappedWebGLTexture: target InternalTexture was not produced by wrapWebGLTexture.\");\r\n        }\r\n\r\n        // Pre-validate before mutating any state so a thrown precondition leaves the InternalTexture untouched.\r\n        // Note: rtWrapper.texture only returns _textures[0]; walk every attachment to catch the multi-RT case where\r\n        // the wrapped texture is at index > 0.\r\n        for (const rtWrapper of this._renderTargetWrapperCache) {\r\n            if (!rtWrapper.textures?.includes(internalTexture)) {\r\n                continue;\r\n            }\r\n            if (rtWrapper.isMulti) {\r\n                throw new Error(\"updateWrappedWebGLTexture: wrapped texture is part of a multi render-target; not supported. Dispose and re-wrap.\");\r\n            }\r\n            if (rtWrapper._depthStencilTexture) {\r\n                // The depth/stencil texture's GL handle was also lost on context restore. Rebuilding it from the\r\n                // wrapper's stored depth settings + re-attaching is feasible but non-trivial; v1 rejects and asks\r\n                // the caller to dispose + re-wrap (which also recreates the depth/stencil texture via the public API).\r\n                throw new Error(\"updateWrappedWebGLTexture: wrapped texture's render-target wrapper has a depth/stencil texture; not supported. Dispose and re-wrap.\");\r\n            }\r\n        }\r\n\r\n        internalTexture._hardwareTexture = new WebGLHardwareTexture(texture, this._gl);\r\n        internalTexture.isReady = true;\r\n\r\n        // The new GL texture has default sampler state; clear the per-InternalTexture cached sampler params so the\r\n        // next _setTexture re-applies them, then drop any binding-cache slot pointing at this InternalTexture so the\r\n        // identity short-circuit (this._boundTexturesCache[channel] === internalTexture) doesn't skip the rebind.\r\n        internalTexture._cachedCoordinatesMode = null;\r\n        internalTexture._cachedWrapU = null;\r\n        internalTexture._cachedWrapV = null;\r","sourceCodeStart":808,"sourceCodeEnd":844,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/core/src/Engines/engine.pure.ts#L808-L844","documentation":"When restoring a wrapped texture, Babylon checks render-target wrappers that reference it. If the texture is an attachment of a multi render-target (rtWrapper.isMulti) or has a depth/stencil attachment, simply swapping the GL handle would leave sibling attachments inconsistent, so v1 rejects and asks the caller to dispose and re-wrap the whole construct.","triggerScenarios":"Calling engine.updateWrappedWebGLTexture on a texture that is an attachment of a multi-render-target wrapper (multiple textures) or whose wrapper has a _depthStencilTexture, e.g. MRT pipelines or depth-enabled wrapped RTs after context loss.","commonSituations":"Context-restoration recovery for MRT (G-buffer) setups using wrapped textures; deferred rendering engines that wrapped each MRT attachment and try to repoint them one by one.","solutions":["Dispose the render target wrapper and recreate it, wrapping the new WebGL textures via wrapWebGLTexture","Exclude textures belonging to isMulti render-target wrappers (and those with depth/stencil attachments) from handle-swap restoration","Restructure so wrapped textures used with MRT are restored through the public render-target creation API","Check rtWrapper.isMulti / rtWrapper._depthStencilTexture before calling updateWrappedWebGLTexture and branch to dispose+re-wrap"],"exampleFix":"// before\nengine.updateWrappedWebGLTexture(mrtTexture, newHandle); // throws: part of MRT\n// after\nif (rtWrapper.isMulti || rtWrapper._depthStencilTexture) {\n  rtWrapper.dispose();\n  const newRt = engine.createMultipleRenderTarget(size, mrtOptions); // then wrap/rebind handles\n} else {\n  engine.updateWrappedWebGLTexture(mrtTexture, newHandle);\n}","handlingStrategy":"validation","validationCode":"const wrapper = engine._renderTargetWrapperCache.find(rtw => rtw.textures?.includes(internalTexture));\nif (wrapper && (wrapper.isMulti || wrapper._depthStencilTexture)) {\n  // dispose and recreate instead of updateWrappedWebGLTexture\n}","typeGuard":"function canRepointInPlace(engine: AbstractEngine, t: InternalTexture): boolean {\n  return !engine._renderTargetWrapperCache.some(rtw => rtw.textures?.includes(t) && (rtw.isMulti || !!rtw._depthStencilTexture));\n}","tryCatchPattern":"try {\n  engine.updateWrappedWebGLTexture(t, newHandle);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('multi render-target')) {\n    rtWrapper.dispose();\n    const rt = engine.createMultipleRenderTarget(size, mrtOptions); // dispose + re-wrap path\n  } else throw e;\n}","preventionTips":["Check rtWrapper.isMulti and _depthStencilTexture before repointing handles","Treat MRT wrappers as atomic: dispose and recreate the whole wrapper on restore","Keep MRT setups on the public render-target API rather than manual wrapping","Document which textures belong to MRT wrappers in your restore pipeline"],"tags":["webgl","mrt","render-target","texture-wrapping","unsupported"],"backgroundTag":"texture-not-externally-wrapped","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}