BabylonJS/Babylon.js · error
updateWrappedNativeTexture: wrapped texture is part of a mul
Error message
updateWrappedNativeTexture: wrapped texture is part of a multi render-target; not supported. Dispose and re-wrap.
What it means
updateWrappedNativeTexture scans the render-target wrapper cache; if the wrapped texture belongs to a multi render-target (MRT) wrapper, updating the underlying handle is unsupported and throws, because MRT framebuffers cannot be safely rebuilt around the swap in this version.
Source
Thrown at packages/dev/core/src/Engines/thinNativeEngine.pure.ts:2184
);
}
if (this._engine.getTextureLayerCount) {
const newLayerCount = this._engine.getTextureLayerCount(texture);
const oldLayerCount = internalTexture.is2DArray ? internalTexture.depth : 1;
if (newLayerCount !== oldLayerCount) {
throw new Error(`updateWrappedNativeTexture: new handle layer count (${newLayerCount}) must match the wrapped texture's layer count (${oldLayerCount}).`);
}
}
// Pre-validate before mutating any state so a thrown precondition leaves the InternalTexture untouched.
// Note: rtWrapper.texture only returns _textures[0]; walk every attachment to catch the multi-RT case where
// the wrapped texture is at index > 0.
for (const rtWrapper of this._renderTargetWrapperCache) {
if (!rtWrapper.textures?.includes(internalTexture)) {
continue;
}
if (rtWrapper.isMulti) {
throw new Error("updateWrappedNativeTexture: wrapped texture is part of a multi render-target; not supported. Dispose and re-wrap.");
}
if (rtWrapper._depthStencilTexture) {
// After a DisableRendering / EnableRendering cycle the bgfx framebuffer + the depth/stencil texture's
// bgfx handle are both stale. Rebuilding the depth/stencil texture from the wrapper's stored settings
// is feasible but non-trivial; v1 rejects and asks the caller to dispose + re-wrap.
throw new Error("updateWrappedNativeTexture: wrapped texture's render-target wrapper has a depth/stencil texture; not supported. Dispose and re-wrap.");
}
}
internalTexture._hardwareTexture = new NativeHardwareTexture(texture, this._engine);
internalTexture.isReady = true;
this.updateTextureSamplingMode(internalTexture.samplingMode, internalTexture);
// Rebuild the framebuffer of any render-target wrapper holding this wrapped texture as its color attachment.
// After a DisableRendering / EnableRendering cycle the bgfx framebuffer handle is stale; the consumer-supplied
// new texture is the moment we have a fresh handle to rebuild against.
for (const rtWrapper of this._renderTargetWrapperCache) {
if (rtWrapper.texture !== internalTexture) {
View on GitHub (pinned to 0592b347b8)
Solutions
- Dispose the MRT wrapper and its textures, then recreate the render target wrapping the new native textures.
- Keep hot-swappable textures in single-attachment render targets instead of MRT.
- Restructure the pass so the swapped texture is not part of the MRT set.
Example fix
// before
engine.updateWrappedNativeTexture(gbuffer.tex[1], newTex); // MRT attachment
// after
mrtWrapper.dispose();
gbuffer = recreateMRT(scene, { texture1: newTex }); Defensive patterns
Strategy: validation
Validate before calling
const inMrt = engine._renderTargetWrapperCache.some(rt => rt.isMulti && rt.textures?.includes(wrapped));
if (inMrt) throw new Error("Texture is an MRT attachment; dispose and recreate the render target instead of updating."); Try / catch
try {
engine.updateWrappedNativeTexture(wrapped, newNativeTex);
} catch (e) {
if (e.message.includes("multi render-target")) {
recreateRenderTargetWithNewTexture(wrapped, newNativeTex);
} else throw e;
} Prevention
- Design G-buffer pipelines to rebuild render targets on texture swap instead of hot-swapping.
- Keep hot-swapped textures out of MRT attachment sets.
- Track which textures belong to MRT wrappers in your renderer state.
When it happens
Trigger: Calling engine.updateWrappedNativeTexture on a texture that appears in rtWrapper.textures of a wrapper with isMulti == true (a texture bound in a multi render-target pass).
Common situations: Deferred-rendering pipelines that swap G-buffer textures created as MRT attachments (position at index > 0); attempting hot-swap of MRT color attachments.
Related errors
- updateWrappedWebGLTexture: wrapped texture is part of a mult
- updateWrappedNativeTexture: wrapped texture's render-target
- updateWrappedNativeTexture: target InternalTexture was not p
- updateWrappedNativeTexture: new handle dimensions (${newWidt
- updateWrappedNativeTexture: new handle layer count (${newLay
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/e0d8a6d463426500.
Report an issue: GitHub.