Conditional rendering

I’m still using OpenGL 2.1 because I want to continue supporting the GEForce 7 series, which I don’t think can run OpenGL3. So I am using the GL_NV_conditional_render extension, or at least trying to. Since drawing shadows is a big bottleneck, and our shadow culling algorithms are imprecise for reasons I won’t go into, this could yield a significant performance gain.

When I call this command, an unhandled exception occurs:
glBeginConditionalRenderNV(queryid,$8E13)

My program structure is as follows:

generate the number of queries needed
For each instance {
QueryBegin()
Draw AABB
QueryEnd()
}
Enable VBOs
For each instance {
begin conditional render
drawelements
end conditional render
}
Disable VBOs

Yes, the extension is supported on the hardware I am using.

Any ideas? Does anyone have experience using this extension?

I have uploaded a test program here:
http://www.leadwerks.com/post/conditional.zip

Here is the source code. The application still crashes on glBeginConditionalRender():

Framework leadwerks.glewex
Import brl.GLGraphics
Import brl.standardio

Graphics 800,600
glewexInit()


Local queryid:Int

glGenQueriesARB(1,Varptr queryid)
Print queryid

glBeginQueryARB(GL_SAMPLES_PASSED_ARB,queryid)
glEndQueryARB(GL_SAMPLES_PASSED_ARB)

glBeginConditionalRenderNV(queryid,$8E13)
glEndConditionalRenderNV()

I got it working, but simply calling glBeginQueryARB / glEndQueryARB causes almost a 10% drop in framerate.

Well you don’t get anything free in this world. :wink:

How complex is your scene?
It may be that the overhead associated with conditional rendering is actually larger than the cost of simply letting the usual culling mechanisms work. But that is just a guess on my part.

I am using this for rendering the shadow of an animated mesh from a point light. I reduced the problem all the way down, so all I was doing was beginning and ending the query, and the mesh would be not drawn because I wan’t drawing anything in the query. The best I could do was about 8% slower than just letting the GPU draw it. I copied the mesh about a dozen times, and the performance just scaled the same with increased numbers…it was never any faster than just letting the mesh render.

I think this is due to the GPU waiting for the query primitive to render before starting the animated mesh. If I use a wait option, it slows the GPU down while it syncs with the end of the query geometry, and if I don’t use a wait option in glbeginconditionalrender, then there is no savings at all.

My guess is you need to render the queries a frame in advanced, sort of like you might with regular occlusion queries that feedback to the CPU.

My guess is you need to render the queries a frame in advanced, sort of like you might with regular occlusion queries that feedback to the CPU.

If you’re going to use conditional render for performance, you have to:

1: Be rendering a scene that actually stresses the card. Test scenes do not work.

2: Kick off the conditional render well after you have launched the query. The best way to do it is to:

a: Render the base terrain that you will always use. Front to back sorted.

b: Render your queries. All of them. Back to front.

c: Render anything else that isn’t connected with conditional renders that you can do at this point.

d: Render your conditional renders for the queries from step ‘b’.

Well, it’s not terrain that is the primary occluder in any scene. Probably the most important occluder is other meshes. Rendering everything but conditionally occluded geometry, then rendering query AABBs, then rendering conditional geometry makes you lose all your gains, which is why I am suggesting it needs to be delayed by one frame. So why bother in the first place, since occlusion queries can save time on the CPU?

Well, it’s not terrain that is the primary occluder in any scene.

That rather depends on your scene, doesn’t it?

There should be some time between your sending occlusion queries and your using the results. That time need not be an entire frame.

That rather depends on your scene, doesn’t it?

Not really. Not for real-world usage.

There should be some time between your sending occlusion queries and your using the results

There’s really nothing to do between building up your depth buffer and drawing those last few expensive objects. I suppose you could have a few depth-only occluders that get drawn first, then make the occlusion queries, and then the regular scene geometry is drawn. I’m just going to stick to occlusion queries.

Not really. Not for real-world usage.

Yes, it does. “Real world usage” does not mean corridor shooters only. There are patterns of rendering usage where terrain is your primary occluding surface.

There’s really nothing to do between building up your depth buffer and drawing those last few expensive objects.

So long as this is the case, for your common scene and for your rendering patters, you will get little use out of conditional render. This need not be the case for others.

see this thread (I never got to the bottom of it), my conclusion was whilst in the spec they say ‘occlusion queries are nearly free’ in reality theyre not

http://www.opengl.org/discussion_boards/…true#Post129545

Since I am writing a general-purpose engine I try to write for the most likely case, instead of justifying bad design with a special case.

The primary problem with queries, I think, is you can’t draw them with instancing. So drawing all those uninstanced boxes is slower than just drawing the instanced full geometry, except for expensive objects.

I use occlusion qureries for animated meshes, lights, and scene zones. Other objects are cheaper just to render without any checks, and using occlusion on zones can dismiss large chunks of the scene. Occlusion queries can also save a significant amount of time on the CPU side. When those large chunks are occluded, that’s a section of the scene the renderer doesn’t even have to iterate through. With queries, I can choose not to re-render a light’s shadows, if it is occluded.

So yeah, my verdict on this is 100% in favor of occlusion queries read by the CPU over conditional rendering. There is a command that allows you to check if a query is ready, so that you don’t force a sync with the GPU.