执行 eglSwapBuffer 和 eglMakeCurrent 时性能低下

12

我正在开发一款Android Unity插件,允许用户记录他/她的游戏过程
我的解决方案概述如下:

  • 使用OpenGL FrameBufferObject(FBO)使Unity呈现屏幕外到这个FBO
  • 获取此FBO的屏幕外纹理,然后用于两个目的:
    • 渲染到视频表面
    • 重新绘制到设备屏幕上
  • 每帧执行以下流程:
    • 绑定我的FBO
    • 将场景渲染到FBO中(Unity代码)
    • 取消绑定我的FBO
    • 设置视频表面
      • 配置表面大小(仅第一次执行)
      • 保存EGL状态
      • 使视频表面成为当前表面
    • 使用我的FBO的屏幕外纹理绘制到视频表面
    • 恢复默认表面
      • 将演示时间设置为视频帧
      • 从视频表面交换缓冲区到默认窗口
      • 恢复EGL状态
      • 使默认表面成为当前表面
    • 通知编码器线程数据已准备好写入

我的问题是录制时性能不好。在三星Galaxy S4上,FPS从60下降到40。我尝试记录渲染操作的执行时间,并意识到最影响性能的操作是使视频表面成为当前表面和从视频表面交换缓冲区到默认窗口操作。以下是它们的代码:

public void makeCurrent()
{
 if (!EGL14.eglMakeCurrent(this.mEGLDisplay, this.mEGLSurface, this.mEGLSurface, this.mEGLContext))
  throw new RuntimeException("eglMakeCurrent failed");
}

public boolean swapBuffers()
{
 return EGL14.eglSwapBuffers(this.mEGLDisplay, this.mEGLSurface);
}

执行当前操作的时间为1~18毫秒
交换缓冲区操作的执行时间为4~14毫秒
其他操作通常为0~1毫秒
如何提高这些操作的性能?
任何帮助都将不胜感激!


1
我目前正在为Unity for Android开发屏幕录制功能。我对你在Unity方面使用的事件来渲染场景到FBO(Unity代码)感兴趣。 你使用了OnPostRender吗?WaitForEndofFrame?还是GL.IssuePluginEvent? 在哪个阶段绑定了FBO?我查看了你在http://forum.unity3d.com/threads/screen-recorder-android-plugin.213466/上的原始代码,但自从4.3版本以后,我相信他们已经改变了UnityPlayer的功能和访问OnDrawFrame不可用。 任何帮助都将是惊人的,谢谢。 - user819640
我也有和 @user819640 一样的问题。在Grafika中,是doFrame回调函数来绘制一帧。我不知道在Unity3D中绘制动作发生在哪里。 - peacepassion
1个回答

0
很多OpenGL调用是异步的,有些调用可能会导致OpenGL等待排队的操作执行。所以你看到的时间是由于在实际调用之前执行的其他调用引起的。

我如何检查哪些调用导致了OpenGl等待排队操作执行? - knighthedspi
@knighthedspi 你需要使用GPU性能分析工具。苹果在Instruments for iOS中包含了一个,我还没有在Android上使用过,但是如果你搜索一下,应该会找到一个。 - fbafelipe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接