Skip to content

fix: skip destroyed struct and stale render element in 2D render pass(2D 渲染跳过已销毁 struct 与失效 render element,修复 GList 虚拟滚动崩溃) - #2341

Open
xiaosong1985 wants to merge 1 commit into
layabox:LayaAir_3.4Tempfrom
xiaosong1985:fix/2d-render-stale-struct-element-crash
Open

Conversation

@xiaosong1985

Copy link
Copy Markdown
Contributor

问题

打开带 fairygui GList 滚动组件的界面、或虚拟列表频繁滚动/回收/销毁重建 item 时,2D 渲染路径出现多处空指针崩溃,例如:

  • Cannot read properties of null (reading 'globalAlpha' / 'globalRenderData') at WebRender2DPass.cullAndSort
  • Cannot read properties of undefined (reading '_handleInterData') at WebRender2DPass.fowardRender
  • Cannot read properties of null (reading 'clipInfo' / '_passes' / 'getClipInfo') at 渲染元素 _compileShader / _render

根因

虚拟滚动在极端 churn 下会频繁 移除+销毁子节点 / 回收 render element。被销毁的 WebRenderStruct2D 及被回收的 render element 仍残留在所属 pass 的 _structs / _renderElements 缓存中;当该 pass 处于「非重绘快路径」时复用这些脏缓存,遍历/绘制到已失效对象 → 读到 null 字段崩溃。核心是结构/元素被销毁回收后,pass 缓存未被正确失效

修复

根因层WebRenderStruct2D):

  • 新增 destroyed 标记,destroy() 置位;
  • removeChild() 在摘除前捕获子节点真实所在的 pass(带 cacheAs/mask 的父,其子渲染在父的 subpass,而非父自身 pass)并标记其 repaint,让缓存重建、不残留对被移除子 struct 的引用。

Pass 层WebRender2DPass):

  • cullAndSort 入口跳过已销毁 struct(原始 globalAlpha 崩溃点兜底);
  • fowardRender mask 分支:subStruct 未就绪/已失效时本帧跳过合成,并保持 repaint 下帧重试;
  • fowardRender 非重绘分支:发现 _structs 缓存含已销毁 struct 时,本帧不绘制脏的 _renderElements 并强制下帧重建。

渲染元素兜底层WebGLRenderElement2D / WebGLPrimitiveRenderElement2D):

  • _prepare / _render 跳过未就绪/已回收的元素(subShader / owner / _curCacheEntry 为空),避免绘制到失效元素崩溃。

验证

在基于 3.4 引擎的工程中用同事提供的必现压力用例复现并验证:1000 项虚拟滚动 GList,每帧疯狂滚动 + itemRenderer 里销毁重建子节点 + 反复切 cacheAs/mask,并每帧递归校验渲染 struct 树父子一致性。

  • 修复前:数十帧内即崩(多处不同空指针)。
  • 修复后:连续跑满 5000 帧无崩溃、无 struct 错位、0 报错

经独立代码审查复核:removeChild 取 pass 时机正确、destroyed 免复位假设成立(createRenderStruct2D 无对象池)、元素级守卫不会误伤正常元素、stale 提前 return 跳过 uploadBuffer 无副作用。

本 PR 仅含共享层 + WebGL 驱动改动,不涉及子模块;WebGPU 驱动的同类元素级守卫将另行补充。

🤖 Generated with Claude Code

…(2D 渲染跳过已销毁 struct 与失效 render element,修复 GList 虚拟滚动频繁销毁/重建子节点时残留缓存引发的多处空指针崩溃)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant