{"record":{"id":"e7c821812a6f0bf3","repo":"BabylonJS/Babylon.js","slug":"updatewrappedwebgltexture-wrapped-texture-s-rende","errorCode":null,"errorMessage":"updateWrappedWebGLTexture: wrapped texture's render-target wrapper has a depth/stencil texture; not supported. Dispose and re-wrap.","messagePattern":"updateWrappedWebGLTexture: wrapped texture's render-target wrapper has a depth/stencil texture; not supported\\. Dispose and re-wrap\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/dev/core/src/Engines/engine.pure.ts","lineNumber":832,"sourceCode":"        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\n        internalTexture._cachedWrapR = null;\r\n        internalTexture._cachedAnisotropicFilteringLevel = null;\r\n        for (const key in this._boundTexturesCache) {\r\n            if (this._boundTexturesCache[key] === internalTexture) {\r\n                this._boundTexturesCache[key] = null;\r\n            }\r","sourceCodeStart":814,"sourceCodeEnd":850,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/core/src/Engines/engine.pure.ts#L814-L850","documentation":"updateWrappedWebGLTexture() re-registers an externally-created WebGL texture after a context-loss/restore event. If the wrapped texture is the color attachment of a render-target wrapper that also owns a depth/stencil texture, that depth/stencil texture's GL handle was also lost and Babylonic v1 does not rebuild it automatically, so the engine throws instead of leaving the render target in a broken state. The comment in the source explicitly says re-attaching is feasible but non-trivial and deferred.","triggerScenarios":"Calling engine.updateWrappedWebGLTexture(texture) on an InternalTexture whose renderTargetWrapper has a non-null _depthStencilTexture after a webglcontextrestored event.","commonSituations":"Apps that manually re-wrap restored WebGL textures after device loss (e.g. mobile browsers, headless rendering, texture sharing with other GL contexts) where the render target was created with a depth/stencil attachment (depthTexture: true or default depth buffer as a texture).","solutions":["Dispose the InternalTexture and recreate it via the public API (createRenderTargetTexture / createDepthStencilTexture) after restore, which rebuilds the depth/stencil attachment too.","Re-wrap the color texture first, then create a new depth/stencil texture and re-attach it to the render target wrapper manually.","If you control target creation, drop the depth/stencil attachment for wrapped targets so this path is never taken."],"exampleFix":"// before\nengine.updateWrappedWebGLTexture(restoredColorTexture);\n// after\nrtWrapper.renderTarget?.dispose();\nconst newRt = engine.createRenderTargetTexture(size, {\n  depthTexture: true,\n  samples: 4\n});\nengine.updateWrappedWebGLTexture(newRt.getInternalTexture());","handlingStrategy":"validation","validationCode":"function canUpdateWrappedTexture(engine, internalTexture) {\n  const rtw = internalTexture.getRenderTargetWrapper?.();\n  return !rtw || !rtw._depthStencilTexture;\n}","typeGuard":"function isUpdatableWrappedTexture(t) {\n  return !!t && !(t.getRenderTargetWrapper?.()?._depthStencilTexture);\n}","tryCatchPattern":"try {\n  engine.updateWrappedWebGLTexture(tex);\n} catch (e) {\n  if (/depth\\/stencil texture/.test(e.message)) {\n    tex.dispose();\n    tex = recreateRenderTargetWithDepth(engine);\n  }\n}","preventionTips":["Track webglcontextrestored and always recreate render targets with depth/stencil attachments via the public API instead of re-wrapping.","Avoid attaching depth/stencil textures to render targets whose color textures you re-wrap.","Centralize context-restore recovery in one helper."],"tags":["webgl","context-loss","textures","render-target"],"backgroundTag":"webgl-context-restore","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}