本文介绍了为什么glClear阻断OpenGLES?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想简介我的渲染器,而我看到一些奇怪的分析行为,我无法解释。

我使用的是glSurfaceView,我已经设置为连续呈现。

这是我的 onDrawFrame()的结构

 公共无效onDrawFrame(GL10未使用){
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
    executeAllDrawCommands();
}
 

这是在轻负载下表现得很慢,所以我创建了一个Timer类,并开始资料这个部分。我是相当通过我所看到的感到惊讶。

我把一些探头在我的onDrawFrame方法,像这样:

 公共无效onDrawFrame(GL10未使用){
   swapTimer.end();

   clearTimer.start();
     GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
   clearTimer.end();

   drawTimer.start();
     executeAllDrawCommands();
   drawTimer.end();

   swapTimer.start();
}
 

clearTimer 测量它需要调用glClear的时候, drawTimer 测量需要运行所有的抽奖时间电话,和 swapTimer 测量时间从什么时候onDrawFrame退出,当它返回(所花费的时间打电话eglSwapBuffers)。

当我跑了很轻负载的场景,我得到了一些非常陌生号码,我无法解释:

  swapTimer:20毫秒(平均)
clearTimer:11毫秒(平均)
drawTimer:2毫秒(平均)
 

我希望交换的时间是有点相当大的,因为我相信该设备已VSYNC被迫使在〜30fps的,虽然我不知道为什么实际的清除呼叫阻塞11毫秒?我以为这只是应该发出一个异步的命令,并返回?

当我画一个更忙碌的景象,这个数字改变了不少:

  swapTimer:2毫秒(平均)
clearTimer:0毫秒(平均)
drawTimer:44ms(平均)
 

在这个场景我绘制调用正在服用了这么多时间,它看起来像它隐藏了许多的VSYNC周期中,并在清晰的通话块完全消失。

有没有为什么glClear阻止我的轻载场景中的任何解释?

链接到我的定时器类的源$ C ​​$ C,以防有人怀疑我的测量技术: http://pastebin.com/bhXt368W

解决方案

这也解释了它。

当你的场景是非常轻和附图渲染速度非常快,清除和填充像素新的颜色需要一定的时间(它总是需要时间的时候,否则渲染器后面,currenty绘制新东东)。较新的Andr​​oid设备有填充率限制。例如,Nexus One的30赫兹有填充率锁 - 屏幕将在该频率再怎么快你的实际的图纸会被同步。如果图纸在30赫兹完成渲染器将同步上涨的屏幕。这就是为什么你看到这种延迟,你应该,如果你删除 glClear()电话通知均匀。该渲染器之前,比屏幕的更新速度加快。

在渲染器有许多对象绘制,同步将暂停(给你的繁忙景象的个人数据),因为渲染是现在屏幕的更新后。

在使用 glfinish在(),它消除了时间 glClear()功能,否则会引起,其中通过以下的填充率的逻辑,意味着 glfinish在()是现在正在保证与画面同步的功能。

计算

F = 1 / T

轻松的场景

F = 1 / T = 1 /((20 + 11 + 2)* 10 ^ -3)=〜30赫兹

同步的延迟时间将出现在您的探查。渲染器是与屏幕同步。这意味着,如果您删除 glClear() glfinish在()电话,延迟将出现在其他地方。

重型场景

F = 1 / T = 1 /((2 + 0 + 44)* 10 ^ -3))=〜22赫兹

同步的延迟时间不会出现在您的探查。渲染是屏幕的更新频率之后。

这似乎是正确的。

I'm trying to profile my renderer, and I'm seeing some weird profiling behavior that I can't explain.

I'm using a glSurfaceView, which I have set to render continuously.

This is how my onDrawFrame() is structured

public void onDrawFrame(GL10 unused) {
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
    executeAllDrawCommands();
}

This was behaving slowly under light load, so I created a timer class and started to profile this some. I was quite surprised by what I saw.

I put some probes on my onDrawFrame method like so:

public void onDrawFrame(GL10 unused) {
   swapTimer.end();

   clearTimer.start();
     GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
   clearTimer.end();

   drawTimer.start();
     executeAllDrawCommands();
   drawTimer.end();

   swapTimer.start();
}

clearTimer measures the time it takes to call glClear, drawTimer measures the time it takes to run all my draw calls, and swapTimer measures the time from when onDrawFrame exits and when it returns (the time taken to call eglSwapBuffers).

When I ran a very lightly loaded scene, I got some really strange numbers I can't explain:

swapTimer  : 20ms (average)
clearTimer : 11ms (average)
drawTimer  :  2ms (average)

I expected the swap time to be somewhat largish, as I believe the device has vsync forced enable at ~30fps, though I don't know why the actual 'clear' call is blocking for 11 milliseconds? I thought it was just supposed to issue an asynchronous command and return?

When I draw a much more busy scene, the numbers change quite a bit:

swapTimer  :  2ms (average)
clearTimer :  0ms (average)
drawTimer  : 44ms (average)

In this scene my draw calls are taking so much time that it looks like its hiding a lot of the vsync period, and the block on the clear call totally goes away.

Is there any explanation for why glClear is blocking on my lightly loaded scene?

Link to my 'Timer' class source code in case someone is suspicious of my measuring technique: http://pastebin.com/bhXt368W

解决方案

That explains it.

When your scene is very light and the drawings are rendered very fast, the time to clear and fill the pixels with the new color will take some time (it will always take time, otherwise the renderer is behind and is currenty drawing new stuff). The newer Android devices have fillrate limits. For example, Nexus One has a fillrate lock at 30 Hz - the screen will be synced at that frequency no matter how fast your actual drawings are going. If the drawings finishes under 30 Hz the renderer will sync up with the screen. This is why you notice this delay, which you should notice even if you remove the glClear() call. The renderer is before and faster than the screen's updates.

When the renderer have many objects to draw, the synchronization will halt (given your busy scene's profile data) because the renderer is now after the screen's updates.

When you use glFinish(), it removes the time the glClear() function otherwise would cause, which, by following the fillrate logic, means that glFinish() is now the function that is ensuring synchronization with the screen.

Calculations:

F = 1/T

Easy scene:

F = 1/T = 1/((20+11+2)*10^-3) =~ 30 Hz

The synchronization's delay time appears in your profiler. Renderer is being synchronized with the screen. That means that if you remove the glClear() or the glFinish() call, the delay would appear somewhere else.

Heavy scene:

F = 1/T = 1/((2+0+44)*10^-3)) =~ 22 Hz

The synchronization's delay time does not appear in your profiler. Renderer is after the screen's update frequency.

That seems to be correct.

这篇关于为什么glClear阻断OpenGLES?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-27 06:25