PDA

View Full Version : ARB_occlusion_query flickering when high FPS



tdname
09-06-2013, 12:39 PM
I'm using OpenGL 3.30 with Shaders (with HW instancing) but I've got a flickering effect on whole scene when I'm trying to execute occlusion queries during high framerates (usually > 100). More pfs I get, then more flickers I get.
With 60 or less fps I get no flickering effect.

YouTube video: http://www.youtube.com/watch?v=i1alFoXrAqY

Pseudo-Code:

Enable off screen rendering to FrameBufferObject
glColorMask(0,0,0,0)
glDepthMask(0)
for each object to render {

Bind VertexBufferObject() to Shader
glBeginQuery(GL_SAMPLES_PASSED)
save QUERY_ID and OBJECT_ID for later use
glDrawArraysInstanced(...)
glEndQuery(GL_SAMPLES_PASSED)


}
while glGetQueryObjectuiv(GL_QUERY_RESULT_AVAILABLE) == 0 {...}
verify if QUERY_ID is visible and set OBJECT_ID the same
glDepthMask(1)
glColorMask(1,1,1,1)
Disable off screen rendering and return to default FrameBuffer
normal Rendering Pass which renders only objects which had QUERY_ID passed as "visible"


I know this is not the good way to "wait" (list point #6) Querie results, but I don't understand why rendering "off screen" (to a FrameBufferObject) starts to flickering in default Framebuffer....Even if I exchange list point #6 with a delay Sleep(500) I get no flickering effect, so the problem is not caused due to wait Query results.

Any idea?

PS: If i remove those piece of code (firsts 10 list points) I get no flickering
PS2: left-bottom text is rendered outside rendering pass

Dark Photon
09-06-2013, 07:37 PM
I'm using OpenGL 3.30 with Shaders (with HW instancing) but I've got a flickering effect on whole scene when I'm trying to execute occlusion queries during high framerates (usually > 100). More pfs I get, then more flickers I get.
With 60 or less fps I get no flickering effect. ...

6. while glGetQueryObjectuiv(GL_QUERY_RESULT_AVAILABLE) == 0 {...}

...I don't understand why rendering "off screen" (to a FrameBufferObject) starts to flickering in default Framebuffer....Even if I exchange list point #6 with a delay Sleep(500) I get no flickering effect, so the problem is not caused due to wait Query results.

The latter statement does not follow.

First, are you rendering with double buffering and sync-to-vblank (i.e. framelock) enabled? If not, stop there and fix that.

Second, 60Hz is 16.66ms/frame. 100Hz is 10ms/frame. Put a glFinish after your SwapBuffers(), and time after this point on the last frame to this same point on the next frame. How long is it? Is it sometimes greater than your vsync frame rate (probably by a multiple)? If so, you're overrunning your frame time budget. You need to fix that. I'd guess that (if you're framelocked correctly) sometimes you're peeking over 10 ms/frame.

And to the point of the efficiency of halting the GPU pipeline and fetching query results back to the CPU to use for conditionally submitting further GPU work, there are more efficient ways to accomplish this which don't involve CPU-GPU synchronization. For instance, look at conditional rendering (http://www.opengl.org/wiki/Vertex_Rendering#Conditional_rendering). Or you can use transform feedback to serialize only objects that pass a frustum and course occlusion cull, and use that in the draw pass. Also look at the recently introduced ARB_query_buffer_object (http://www.opengl.org/registry/specs/ARB/query_buffer_object.txt).

And if for some reason you really, really want to keep the CPU get query approach in-place, be sure you're at least doing a glFlush() after submitting your last query before you do the get queries. If you don't your queries might just sit idle on the CPU side for a while in a to-GPU "send buffer" and thus not get promptly processed on the GPU.

I don't completely understand why your default framebuffer is flickering. If you are clearing the color buffer, are single buffered (an error), are framelocked, and are overrunning your frametime budget (also an error), I could potentially see something like this happening.

carsten neumann
09-07-2013, 10:27 AM
Have you checked that the occlusion queries produce sensible results across multiple frames, i.e. they don't change from frame to frame without a change in camera or object position to explain that change?

You disable depth writes while rendering for the occlusion queries, which seems odd to me since the only objects that should be classified as occluded under these circumstances are those outside the view frustum everything else will be visible: there is nothing to occlude it.

tdname
09-08-2013, 01:50 AM
are you rendering with double buffering and sync-to-vblank enabled? If not, stop there and fix that
Double Buffering is active but VSync not due to test the framerate.
I've implemented an option (with a checkbox) to enable or disable VSync before start my engine. I'm usual to disable it when I want to see if newest source code changes have improved or not the speed of rendering...and how much improved...
If I enable VSync I get no any flickering effect.
Sorry for this my lack in before explanation.


If so, you're overrunning your frame time budget
I'll test your suggestion tomorrow (now I'm not at home), but I don't understand what you were meaning with those words I've quoted (english is not my main language, and I don't understand well the meaning of your phrase)...


sometimes you're peeking over 10 ms/frameOf course the milliseconds can reach 5ms when 200fps are reached.
But it should not happen. If the milliseconds goes down, the Query time remains fixed. In my code I'm waiting Queries results with the loop at row #6 of previously pseudo-code, so the FrameTime should not fall below certain values which mainly depends on this loop at #6.
Even if the whole rendering could take only 1ms, the loop at #6 increase this milliseconds until all Queries are done.
Infact if I replace #6 with "Sleep(500)" I get very low framerate.
With #6 if all Queries are not done the code remains in the loop, in other works the code remains in same frame waiting in the loop.......or not?

Even with "glFinish()" between #5 and #6 (of pseudo-code) the flickering still present :(


look at conditional rendering (http://www.opengl.org/wiki/Vertex_Rendering#Conditional_rendering)
Unfortunately I've already discarded conditional rendering because the CPU doesn't knows nothing about conditional rendering result, so I'm not able to set any source code's variable with occlusion result. I need this query result at CPU time to discard even its object's childs which could be INSIDE its boundaries. Example: please consider a box which physically contains small balls...if the box is occluded, I don't need to check occlusion (neither with conditional render) for each contained ball in it. To do this I need a variable filled with Occlusion Query result.
Conditional rendering only tries to render the object, but can't instructs the CPU of its result.


recently introduced ARB_query_buffer_object (http://www.opengl.org/registry/specs/ARB/query_buffer_object.txt)
Unfortunately my GPU is on a notebook and supports at least OpenGL 3.3....


If you are clearing the color buffer
I clear the FrameBuffer on which I render on "off screen" to execute occlusion culling rendering, but not the default framebuffer on which I render at the end, this because all scene pixels are always renewed every frame (I'm using sky boxes/spheres), so I chose to discard that not useful function call.


You disable depth writes while rendering for the occlusion queries
I understand your doubt but all OcclusionQuery examples I've found online had this piece of code in it...

GClements
09-08-2013, 07:44 AM
You disable depth writes while rendering for the occlusion queries, which seems odd to me since the only objects that should be classified as occluded under these circumstances are those outside the view frustum everything else will be visible: there is nothing to occlude it.
Disabling depth writes is fine if you're just trying to query whether a given object is occluded by whatever is already in the depth buffer. Moreover, if the mesh used for the occlusion query is just a bounding volume, or if you're skipping alpha tests (or some other aspect of the rendering process which affects which fragments are drawn), then disabling depth writes is necessary.