单独停止RenderThread不停止GameThread方案

功能场景为引擎AAR的方式集成到安卓工程,设计有两个窗口surfaceview,需要引擎动态切换surface绘制

当前实现方案:

  1. 每次切换surface时,先停止引擎渲染,再设置新的surface给引擎绘制,再调用命令重启拉起引擎
  2. 如果切换surface时,下一个surface还没有创建,先提供一个TempSurface给引擎绘制(调用setTempSurfaceToUE),等待下一个surface创建再替换

以上流程在安卓主线程操作,可能阻塞线程,且因为层级切换功能层级频繁,会频繁调用命令触发引擎停止和启动,整体代码性能较差,偶尔会出现切换surface时,长时间阻塞主线程。

<br/>

是否有更合适的方案,满足如下需求:

  1. 确保在切换surface时,如果surface无效,引擎继续更新(引擎线程不停止或只停止渲染线程绘制),surface创建时,引擎可以立即往新surface绘制
  2. 涉及多屏绘制,只有主屏不显示,如何将主屏的渲染消耗关闭?

<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);
}`

您好,抱歉回复晚了,问题被分到总部去了

渲染线程是无法完全停止的,因为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也不会生成