5

I have several (potentially thousands) of scenes I would like to render in order to perform queries on what is drawn. The problem I am running into is that calls to glGetQueryObjectiv() are expensive, so I'd like to figure out a way to render several scenes in advance while I wait for the results of the queries to become available.

I have read a bit about Framebuffer Objects and Pixel Buffer Objects, but mostly in the context of saving to a file using glReadPixels() and I haven't been able to track down an example of using either of these objects in asynchronous queries. Is there any reason why the setup for performing glGetQueryObjectiv() would be different from glReadPixels() as in this example (e.g., should I use an FBO or a PBO)?

Note: This is NOT for a graphics application. All I'm interested in is the result of the GL_SAMPLES_PASSED query (i.e. how many pixels were drawn?).

The specific application is estimating how much sunlight is striking a surface when other surfaces are casting shadows. If you are interested, you can read about it here.

Community
  • 1
  • 1
Neal Kruis
  • 2,055
  • 3
  • 26
  • 49
  • Also, keep in mind that `GL_SAMPLES_PASSED` is not the number of pixels drawn *per-se*. It is the number of samples that pass depth tests (it does not discount a sample if it would have failed a stencil/alpha test or been discarded by a fragment shader). Furthermore, 1 sample != 1 fragment. If you have multi-sampling enabled the number will potentially be different than if you use single sampling, based on coverage (though the exact behavior is actually implementation defined). – Andon M. Coleman Jan 13 '14 at 21:25

1 Answers1

2

Neither Framebuffer Objects nor (Pixel) Buffer Objects are the proper class of objects to use in an (asynchronous) query; GL has an entirely separate class of objects called Query Objects. You can feed the results of certain queries into Buffer Objects, but that is about as far as their relationship goes.

Basically the idea with asynchronous queries is that you put the query into the graphics pipeline and let some time pass before you try to read it back. This gives the GPU time to actually finish all of the commands in between the beginning and end of your query first. The alternative is a synchronous query, which means that your calling thread stops doing anything useful and waits for the GPU to finish everything necessary to complete your query.

The simplest way of implementing a query that does not force synchronization would be to start and finish your query as you would typically, but rather than reading the result immediately, in your application's main loop periodically check the status of GL_QUERY_RESULT_AVAILABLE for your query object. When this gives you GL_TRUE, it means you can read the results from the query object without disrupting the render pipeline. If you do try to get the results from a query object before it is in this state, you are going to force a synchronous query.

Andon M. Coleman
  • 42,359
  • 2
  • 81
  • 106
  • 1
    To take advantage of asynchronous queries, I need to do something else to keep my application busy while I wait for the results to become available. My thought is that I can queue up several renderings (perhaps into Framebuffer Objects) and perform the queries. As the query results become available I can queue up additional renderings to keep the application busy. Are you saying I don't need extra buffer objects to create these renderings? – Neal Kruis Jan 13 '14 at 20:06
  • 1
    @NealKruis: That is correct. All you need are multiple query objects (one for each frame/scene you want to query in your scenario). I think you need to visualize rendering as the in-order pipelined process that it really is to fully appreciate why you do not need multiple FBOs to accomplish this. Queries basically encapsualte a sequence of commands, and return some information about the results after they finish. – Andon M. Coleman Jan 13 '14 at 20:10