针对 iOS 14 Web 端性能问题的解决方案

原文地址:https://forum.cocos.org/t/topic/97808/15?u=sr5220


经过验证,此问题波及 iOS 14 上的所有浏览器、WebView 运行环境,小游戏和原生游戏不受影响。引擎组立即着手调试,经过一天的排查,发现这个问题的症结在 vb 和 ib 的共享上。


为优化性能,Creator 多个 drawcall 之间会共享同一份 vb 和 ib,每个 drawcall 使用一个偏移值在共享 vb 和 ib 中找到本次渲染的数据,但是经过我们验证后发现,共享 vb 和 ib 会导致在 iOS 14 上性能下降非常严重。



所以修复此问题的关键就是,在提交 drawcall 之后,切换 vb 和 ib。经过修改,问题就能得到完全解决。

  解决方案: 

> 2.2 版本:

 

在项目脚本最外层加入如下代码,直接覆盖 cc.MeshBuffer 中的方法即可。

const isIOS14Device = cc.sys.os === cc.sys.OS_IOS && cc.sys.isBrowser && cc.sys.isMobile && /iPhone OS 14/.test(window.navigator.userAgent);if (isIOS14Device) {    cc.MeshBuffer.prototype.checkAndSwitchBuffer = function (vertexCount) {        if (this.vertexOffset + vertexCount > 65535) {            this.uploadData();            this._batcher._flush();        }    };    cc.MeshBuffer.prototype.forwardIndiceStartToOffset = function () {        this.uploadData();        this.switchBuffer();    };}

也可以自定义引擎,手动合并此PR:https://github.com/cocos-creator/engine/pull/7415 。


2.1.x 版本

 

原理和 2.2 一样,首先在项目脚本最外层加入如下代码,直接覆盖 cc.MeshBuffer 中的方法。

const isIOS14Device = cc.sys.os === cc.sys.OS_IOS && cc.sys.isBrowser && cc.sys.isMobile && /iPhone OS 14/.test(window.navigator.userAgent);if (isIOS14Device) {    cc.MeshBuffer.prototype.checkAndSwitchBuffer = function (vertexCount) {        if (this.vertexOffset + vertexCount > 65535) {            this.uploadData();            this._batcher._flush();        }    };    }


但 2.1 中没有实现 forwardIndiceStartToOffset,所以你还需要自定义引擎并找到 model-batcher.js,将 _flush 方法中的最后三行改为:

        const isIOS14Device = cc.sys.os === cc.sys.OS_IOS && cc.sys.isBrowser && cc.sys.isMobile && /iPhone OS 14/.test(window.navigator.userAgent);
_flush () {    let material = this.material,        buffer = this._buffer,        indiceStart = buffer.indiceStart,        indiceOffset = buffer.indiceOffset,        indiceCount = indiceOffset - indiceStart;    if (!this.walking || !material || indiceCount <= 0) {        return;    }
   let effect = material.effect;    if (!effect) return;
   // Generate ia    let ia = this._iaPool.add();    ia._vertexBuffer = buffer._vb;    ia._indexBuffer = buffer._ib;    ia._start = indiceStart;    ia._count = indiceCount;
   // Generate model    let model = this._modelPool.add();    this._batchedModels.push(model);    model.sortKey = this._sortKey++;    model._cullingMask = this.cullingMask;    model.setNode(this.node);    model.setEffect(effect, this.customProperties);    model.setInputAssembler(ia);    this._renderScene.addModel(model);
   if (isIOS14Device) {        buffer.uploadData();        buffer.switchBuffer();    }    else {        buffer.byteStart = buffer.byteOffset;        buffer.indiceStart = buffer.indiceOffset;        buffer.vertexStart = buffer.vertexOffset;    }},

            

2.0.x 版本


自定义引擎,并用此文件 https://forum.cocos.org/uploads/default/original/3X/2/6/2699adeb70a987f69ea2d72a5c5c953279c235dd.zip 覆盖引擎中的 mesh-buffer.js,然后再使用和 2.1.x 版本相同的改动方式修改。


注意:自定义引擎后需要重新编译引擎才能生效。建议合并后,使用不同手机进行全面测试。


上一篇:无

下一篇:微信小游戏模糊问题