android 旋转屏幕闪退问题

RenderPass对象被释放而使用RenderPass的FrameBuff未被释放
旋转触发 cmdFuncGLES3CreateFramebuffer 的时候使用了错误的RenderPass
image
image

@Yuan2333 @Knox @minggo

产生的原因就是 renderpass 对象池 和 framebuff 对象池 对象释放不统一,因为 framebuff 使用了renderpass 对象, 在renderpass gc的时候 使用对应renderpass 的 framebuff 未被gc ,这个时候framebuff使用的renderpass 就是一个被释放的内存块了,如果这个内存块被修改了,然后触发旋转导致framebuff 需要重新执行 cmdFuncGLES3DestroyFramebuffer cmdFuncGLES3CreateFramebuffer 这时候就出现闪退了

还有个问题就是GLES3GPUFramebufferHub::update 做
cmdFuncGLES3DestroyFramebuffer
cmdFuncGLES3CreateFramebuffer
的时候 没有清理 storeInvalidates 会导致这个数组越来越大

修改了FrameBuff 的对象池 在对象创建和对象释放的同时 对RenderPass 做引用计数

另外 android 调试如果在控制台执行 cc.game.restart() 操作有概率会崩溃 崩溃的原因是 cc.game.restart() 执行的时机 是在c++调用js逻辑的开始执行 所以有概率会在rootProto._onDirectorBeforeRender = function () {
legacyCC.director.emit(legacyCC.Director.EVENT_BEFORE_RENDER);
};
渲染事件分发前执行 因为
cc.game.restart = function () {
// Need to clear scene, or native object destructor won’t be invoke.
cc.director.getScene().destroy();
cc.Object._deferredDestroy();
__restartVM();
};
会做清理导致后续操控空指针也会闪退

官方现在是个什么情况 一点反应都没有 3.7.3就有的问题

给你顶一顶

3.7 的也可以按照我说的那样去改对象池 目前我们测试已经是没问题的了

你好,感谢反馈,请问出现问题的设备是arm-v8a, 还是arm-v7a? 有什么方式可以必现的吗
目前我这边能复现的是armv7a 架构。我们最近修复一个32位系统上的bug,请合并后验证,谢谢

https://github.com/cocos/cocos-engine/pull/17172, 麻烦合并这个pr后验证;修复32位系统上的问题

我说的这个问题 是需要native 旋转屏才会崩溃 和你这个不一样,原因就是RenderPass 被释放掉了 想复现 就是写个旋转方法一直旋转 30秒有个对象池gc 有一定概率把 FrameBuff 使用的 RenderPass gc掉 ,在native 旋转的时候 所有的FrameBuff 需要用 RenderPass 执行 cmdFuncGLES3DestroyFramebuffer
cmdFuncGLES3CreateFramebuffer 在执行 create的时候需要使用 RenderPass 这时候就概率崩溃了 因为这段内存被释放了 如果没人重写这段内存还能跑 如果有人改了 就会出现各种空指针 或者 数组越界 的崩溃

目前是在对象池里加了 对 RenderPass 的引用计数
另外一个问题 旋转的时候 有2个数组没有清空 每次旋转 数组就会变大 cmdFuncGLES3CreateFramebuffer 会往数组里面添加 删除的时候没有清空 每次旋转数组就扩大n

我这边旋转屏幕的时候,测试次数多点,相对容易重现;合并了上面的 修改后,暂时未复现;
上面那个pr 修复的是因为hash导致该释放的没释放,可能会去释放不该释放的,因为hash值不统一。

写旋转的方法,定时执行? 有具体demo?

定时执行 200次把 然后旋转 就是调用 android 原生的旋转 使用雷电模拟器9.0.73 64位

数组变大的是必现 ,renderpass 被释放的 比较难复现 我们这边有些电脑复现很快 有些很慢 检验把电脑内存占用率弄高 点 需要 renderpass 被释放的内存 被修改 才会出现 如果只是renderpass 被释放好像不会立马出现 ,因为指针指向的那段内存还没被修改,其实看代码逻辑就能看出明显会出现renderpass被释放 而使用他的 framebuff 还存在的问题 或者你在创建 renderpass 和 framebuff 的地方加日志 也能看出来 因为renderpass 和 framebuff 从对象池取对象的hash值方案就不一致