功能场景为引擎AAR的方式集成到安卓工程,设计有两个窗口surfaceview,需要引擎动态切换surface绘制
当前实现方案:
- 每次切换surface时,先停止引擎渲染,再设置新的surface给引擎绘制,再调用命令重启拉起引擎
- 如果切换surface时,下一个surface还没有创建,先提供一个TempSurface给引擎绘制(调用setTempSurfaceToUE),等待下一个surface创建再替换
以上流程在安卓主线程操作,可能阻塞线程,且因为层级切换功能层级频繁,会频繁调用命令触发引擎停止和启动,整体代码性能较差,偶尔会出现切换surface时,长时间阻塞主线程。
<br/>
是否有更合适的方案,满足如下需求:
- 确保在切换surface时,如果surface无效,引擎继续更新(引擎线程不停止或只停止渲染线程绘制),surface创建时,引擎可以立即往新surface绘制
- 涉及多屏绘制,只有主屏不显示,如何将主屏的渲染消耗关闭?
<br/>
重现步骤
`//surface生命周期监听
public class SurfaceHolderCallback implements SurfaceHolder.Callback {
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
++logOrder;
renderSurfaceHolder = holder;
renderSurface = holder.getSurface();
// Surface创建时,且UE初始化完成了,再执行先停止引擎的操作,准备通知引擎切换Surface
if (!renderSurfaceValid && bResuming && bUEInitComplete) {
//释放之前的ANativeWindow
Log.i("SwitchSurface", "Call MainSurface surfaceChanged Start Call EngineCommand APP_CMD_TERM_WINDOW");
GameActivity.Get().nativeAppCommand(APP_CMD_TERM_WINDOW);
Log.i("SwitchSurface", "Call MainSurface surfaceChanged End Call EngineCommand APP_CMD_TERM_WINDOW");
pauseUeRenderImmediately();
}
GameActivity.Get().nativeSetSurfaceOverride(renderSurface, renderSurfaceViewPosition[0], renderSurfaceViewPosition[1]);
//如果前后调用surfaceChanged对应的Surface不一致,应该执行重新创建ANativeWindow的逻辑
//Surface先执行了SurfaceCreate再执行surfaceChanged,才需要走重新拉起应用的逻辑
if (!renderSurfaceValid) {
renderSurfaceValid = true;
if (bResuming) {
//主Surface和第二屏Surface都出于无效状态下,显示主Surface通知UE画面启动
resumeUeRender();
GameActivity.Get().nativeResumeMainInit();
//设置新的ANativeWindow
GameActivity.Get().nativeAppCommand(APP_CMD_INIT_WINDOW);
GameActivity.Get().nativeAppCommand(APP_CMD_GAINED_FOCUS);
}
}
GameActivity.Get().nativeSetSurfaceViewInfo(width, height);
bMainSurfaceIsValid = true;
if (bResuming) {
onPauseCounter = 0;
bResuming = false;
}
}
//surface无效时,采用临时surface提供引擎继续运行绘制
public static Surface GetTempMainSurface() {
if (surfaceTextureForInit == null) {
surfaceTextureForInit = new SurfaceTexture(0);
int width = 8;
int height = 8;
surfaceTextureForInit.setDefaultBufferSize(width, height);
}
if (surfaceForInit == null) {
surfaceForInit = new Surface(surfaceTextureForInit);
}
return surfaceForInit;
}
public void SetTempSurfaceToUE() {
Log.i(“SwitchSurface”, "SurfaceDebug ####### :Call SetTempSurfaceToUE 11 !!! ");
GetTempMainSurface();
//释放之前的ANativeWindow
GameActivity.Get().nativeAppCommand(APP_CMD_TERM_WINDOW);
pauseUeRenderImmediately();
GameActivity.Get().nativeSetSurfaceOverride(surfaceForInit, 0, 0);
resumeUeRender();
//创建新的ANativeWindow
GameActivity.Get().nativeAppCommand(APP_CMD_INIT_WINDOW);
GameActivity.Get().nativeAppCommand(APP_CMD_GAINED_FOCUS);
}`
tuo.chen
(tuo.chen)
3
您好,抱歉回复晚了,问题被分到总部去了
渲染线程是无法完全停止的,因为Game线程会同步,如果没有使用slate的话,可以使用 showflag.rendering 0 跳过渲染线程绝大部分的执行逻辑
另外4.27需要加入这个修改:https://github.com/EpicGames/UnrealEngine/commit/43dc6cb74f5f2dd28007eabef0da994b99a02370
如果是多屏渲染,则不可以用 showflag.rendering 0,因为这个是将所有view的渲染都停止,
4.27多屏方案,副屏使用的是scenecapture,一般来说可以替换一个1x1的RT,可以减掉大部分的GPU占用,同时将main camera的 far clip plane 设置为near clip plane + 0.01,则大部分的mesh draw call也不会生成