Why is glClear locking in OpenGLES?

I am trying to profile my renderer and I see some strange profiling behavior that I cannot explain.

I am using glSurfaceView, which I have set up to render continuously.

This is how my onDrawFrame() structured

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

This showed up slowly under light load, so I created a timer class and started working on some of them. I was very surprised to see.

I put some probes in my onDrawFrame method as follows:

 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 complete all my drawing calls, and swapTimer measures the time from when onDrawFrame exited and when it returns (time spent calling eglSwapBuffers).

When I launched a very busy scene, I got some really strange numbers that I can not explain:

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

I expected the swap time to be somewhat longer, since I believe the device had vsync forcibly turned on at ~ 30 frames per second, although I don't know why the actual β€œclear” call is blocked for 11 milliseconds? I thought it was just supposed to issue an asynchronous command and return?

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

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

In this scene, my drawing calls take so much time that it looks like it hides a lot of vsync time, and the block with the clear call completely leaves.

Is there any explanation why glClear blocks my slightly loaded scene?

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

+8
android opengl-es glsurfaceview
source share
1 answer

I put glFinish (and finishTimer.start () / end () around it) and it takes all the time from glClear. Instead, glFinish takes a few milliseconds, and glClear becomes instant.

This explains this.

When your scene is very bright, and the pictures are rendered very quickly, the time required to clean and fill the pixels with a new color will take some time (it will always take time, otherwise the current material will also render). Newer Android devices have fill limits. For example, the Nexus One has a 30 Hz fill lock - the screen will synchronize at that frequency no matter how fast your actual drawings run. If the drawings end up to 30 Hz, the rendering will synchronize with the screen. This is why you notice this delay, which you will notice even if you delete the glClear() call. The renderer works up to and faster than on-screen updates.

When there are many objects to draw in the renderer, the synchronization will be stopped (taking into account the data of your active plot profile), since the rendering is now after updating the screen.

When you use glFinish() , it removes the time, otherwise calling the function glClear() , which, following the filling logic, means that glFinish() now a function that synchronizes with the screen.

Calculations

F = 1 / t

Easy scene :

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

The profiler displays the delay time for synchronization. Renderer syncs with the screen. This means that if you delete the call to glClear() or glFinish() , a delay will appear elsewhere.

Heavy scene :

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

The synchronization delay time is not displayed in the profiler. Renderer after screen refresh rate.

It all seems to be related to vsync

That seems right.

+10
source share

All Articles