From d2ecc169b1e1fc2219f252a39d2199a1e57e7973 Mon Sep 17 00:00:00 2001 From: hakastein Date: Wed, 29 Jul 2026 20:51:58 +0200 Subject: [PATCH] fix(pipeline): keep MANAGED render targets alive across frames in release builds pipeline.resourceUses is filled only by Compiler, which does not contribute in a release build: web-pipeline.ts wraps the compiler in `if (DEBUG)`, and the RasterPass node is created with `valid = !DEBUG` so _fetchValidPass returns before the loop that fills the list. Executor._removeDeviceResource then finds no name in it and releases every MANAGED device texture and buffer, so the cascaded shadow map was reallocated once per frame. Collect the names from the frame's render graph before the sweep instead. --- cocos/rendering/custom/executor.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/cocos/rendering/custom/executor.ts b/cocos/rendering/custom/executor.ts index ffcbfd764f4..1328be70470 100644 --- a/cocos/rendering/custom/executor.ts +++ b/cocos/rendering/custom/executor.ts @@ -1686,6 +1686,22 @@ export class Executor { private _removeDeviceResource (): void { const pipeline: any = context.pipeline; const resourceUses = pipeline.resourceUses; + // Names this frame's graph references. Compiler is the only other writer of this list and + // it does not contribute in release builds, so without this every MANAGED resource reads as + // unused and is released and reallocated once per frame. + const rg = context.renderGraph; + const use = (resName: string): void => { + if (!resourceUses.includes(resName)) resourceUses.push(resName); + }; + for (let v = 0; v !== rg.nv(); ++v) { + if (rg.h(RenderGraphValue.RasterPass, v)) { + const rasterPass = rg.j(v); + for (const [resName] of rasterPass.rasterViews) use(resName); + for (const [resName] of rasterPass.computeViews) use(resName); + } else if (rg.h(RenderGraphValue.Compute, v)) { + for (const [resName] of rg.j(v).computeViews) use(resName); + } + } const deletes: string[] = []; const deviceTexs = context.deviceTextures; for (const [name, dTex] of deviceTexs) {