Multiple occlusion queries

Hello, I’m trying to compute the area of each visible triangle from a camera position. I’m using occlusion queries, the extension GL_ARB_occlusion_query that returns the area with the function glGetQueryObjectuivARB.
The problem is the following: if I use only one query, always waiting for the results, it works fine. But I’m working with objects with more than 100 000 polygons, and of course I need faster results. So, now I’m using several queries. First, I send all the queries, and then I read the results. If I use this second option sometimes some queries return a value -2029285368, this value should be always positive (uint). What’s happening?. Maybe the query hasn’t a result yet. How can the system wait for all the results? Any idea?

Thank you in advance,
Pascual.

GLuint available;
do {
    DoSomeStuff();
    glGetQueryObjectivARB(queries[i], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
} while (!available);

Read this for more details.

[Edit: GLuint instead of boolean]

Originally posted by MickeyMouse:
[b]

bool available;
do {
    DoSomeStuff();
    glGetQueryObjectivARB(queries[i], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
} while (!available);

Read this for more details.[/b]
Thank you, but I’ve tried this and still it gives me the same results (some queries return -2029285368).

have u first called the command that saiz if the query is finished? its in the spec

Originally posted by zed:
have u first called the command that saiz if the query is finished? its in the spec
Thank you, but I can’t find that command. What I’m doing is this:

GLuint *queries;

// Generate a list of occlusion queries
queries = (GLuint *)malloc(mesh->numTriangles * sizeof(GLuint));
glGenQueriesARB(mesh->numTriangles, queries);

renderGeometry();

void getSWHistoByOcclusionQuery(void) {
GLuint i, v1, v2, v3;

glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDepthMask(GL_FALSE);

for (i=0; i<mesh->numTriangles; i++) { // For every triangle
    glBeginQueryARB(GL_SAMPLES_PASSED_ARB, queries[i]);

    // Render triangle i
    glBegin(GL_TRIANGLES);
    ...
    glEnd();

    glEndQueryARB(GL_SAMPLES_PASSED_ARB);
}
glFlush();

glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_TRUE);

for (i=0; i<mesh->numTriangles; i++) { // For every triangle

    glGetQueryObjectuivARB(queries[i], GL_QUERY_RESULT_ARB, &fullHistogram[i + 1]);

    if (fullHistogram[i + 1] ==  -2029285368) { // NVIDIA value
        printf("    t:%d a:%d

", i, fullHistogram[i + 1]);
fullHistogram[i + 1] = 0;
}
}

fullHistogram[0] = computeBackgroundArea(width, height, mesh->numTriangles); // Compute area of the background

}

You’re not doing anything I pointed out, nor you haven’t read the spec :wink:
Notice the difference between GL_QUERY_RESULT_ARB in your code and GL_QUERY_RESULT_AVAILABLE_ARB in piece of code I gave you.

Put this:

bool available;
do {
    glGetQueryObjectivARB(queries[i], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
} while (!available);

before:

glGetQueryObjectuivARB(queries[i], GL_QUERY_RESULT_ARB, &fullHistogram[i + 1]);

in your code and it’ll be fine.

sorry i didnt see that MickeyMouse had already said beforehand (in greater detail to boot) than what i said,
my defense is is it possible to make the code: block with a larger(or more clear) font. it looks like 7pt courier, better fixed width fonts are Bitstream Vera Sans Mono or lucidia console

Originally posted by MickeyMouse:
[b]You’re not doing anything I pointed out, nor you haven’t read the spec :wink:
Notice the difference between GL_QUERY_RESULT_ARB in your code and GL_QUERY_RESULT_AVAILABLE_ARB in piece of code I gave you.

Put this:

bool available;
do {
    glGetQueryObjectivARB(queries[i], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
} while (!available);

before:

glGetQueryObjectuivARB(queries[i], GL_QUERY_RESULT_ARB, &fullHistogram[i + 1]);

in your code and it’ll be fine.[/b]
Thank you, but I tried this before and it didn’t work, I still get some -2029285368 values and they are not always in the same queries.

 void getSWHistoByOcclusionQuery(void) {
    GLuint i, v1, v2, v3;
    int available;

    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
    glDepthMask(GL_FALSE);

    for (i=0; i<mesh->numTriangles; i++) { // For every triangle
        glBeginQueryARB(GL_SAMPLES_PASSED_ARB, queries[i]);

        // Render triangle i
        glBegin(GL_TRIANGLES);
        ...      

        glEnd();

        glEndQueryARB(GL_SAMPLES_PASSED_ARB);
    }
    glFlush();

    // Wait for all queries
    i = mesh->numTriangles - 1;
    do {   
        glGetQueryObjectivARB(queries[i], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
    } while (!available);

    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
    glDepthMask(GL_TRUE);

    for (i=0; i<mesh->numTriangles; i++) { // For every triangle

        glGetQueryObjectuivARB(queries[i], GL_QUERY_RESULT_ARB, &fullHistogram[i + 1]);

        if (fullHistogram[i + 1] ==  -2029285368) { // NVIDIA value
            printf("    t:%d a:%d
", i, fullHistogram[i + 1]);
            fullHistogram[i + 1] = 0;
        }
    }

    fullHistogram[0] = computeBackgroundArea(width, height, mesh->numTriangles); // Compute area of the background
} 

I’m wondering if it is an implementation problem. I’m running on a NVIDIA Quadro NVS 280 PCI-E. Anybody knowns what maybe is wrong?.

You’re still simply doing it wrong way. You don’t wait for ALL occlusion results, but just for the last one.
Here’s what you should have:

Originally posted by castellp:
[b]

 void getSWHistoByOcclusionQuery(void) {
    GLuint i, v1, v2, v3;
    int available;
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDepthMask(GL_FALSE);
for (i=0; i<mesh->numTriangles; i++) { // For every triangle
    glBeginQueryARB(GL_SAMPLES_PASSED_ARB, queries[i]);
    // Render triangle i
    glBegin(GL_TRIANGLES);
    ...      
    glEnd();
    glEndQueryARB(GL_SAMPLES_PASSED_ARB);
}
glFlush();
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_TRUE);
for (i=0; i<mesh->numTriangles; i++) { // For every triangle
    // !!!!!!! Wait for i-th query !!!!!!
    do {   
        glGetQueryObjectivARB(queries[i], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
    } while (!available);
    glGetQueryObjectuivARB(queries[i], GL_QUERY_RESULT_ARB, &fullHistogram[i + 1]);
    if (fullHistogram[i + 1] ==  -2029285368) { // NVIDIA value
        printf("    t:%d a:%d

", i, fullHistogram[i + 1]);
fullHistogram[i + 1] = 0;
}
}

fullHistogram[0] = computeBackgroundArea(width, height, mesh->numTriangles); // Compute area of the background

}

I'm wondering if it is an implementation problem. I'm running on a NVIDIA Quadro NVS 280 PCI-E. Anybody knowns what maybe is wrong?.[/b]

Originally posted by MickeyMouse:
[b]You’re still simply doing it wrong way. You don’t wait for ALL occlusion results, but just for the last one.
Here’s what you should have:

 void getSWHistoByOcclusionQuery(void) {
    GLuint i, v1, v2, v3;
    int available;
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDepthMask(GL_FALSE);
for (i=0; i<mesh->numTriangles; i++) { // For every triangle
    glBeginQueryARB(GL_SAMPLES_PASSED_ARB, queries[i]);
    // Render triangle i
    glBegin(GL_TRIANGLES);
    ...      
    glEnd();
    glEndQueryARB(GL_SAMPLES_PASSED_ARB);
}
glFlush();
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_TRUE);
for (i=0; i<mesh->numTriangles; i++) { // For every triangle
    // !!!!!!! Wait for i-th query !!!!!!
    do {   
        glGetQueryObjectivARB(queries[i], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
    } while (!available);
    glGetQueryObjectuivARB(queries[i], GL_QUERY_RESULT_ARB, &fullHistogram[i + 1]);
    if (fullHistogram[i + 1] ==  -2029285368) { // NVIDIA value
        printf("    t:%d a:%d

", i, fullHistogram[i + 1]);
fullHistogram[i + 1] = 0;
}
}

fullHistogram[0] = computeBackgroundArea(width, height, mesh->numTriangles); // Compute area of the background

}

I'm wondering if it is an implementation problem. I'm running on a NVIDIA Quadro NVS 280 PCI-E. Anybody knowns what maybe is wrong?.[/b]

[/b]</font><hr /></blockquote><font size=“2” face=“Verdana, Arial”>You are right, I was waiting only for the last query, I have tried your code but still I get some negative values. Really, this has no sense.

MickeyMouse, what you propose is nonsense. Querying for GL_QUERY_RESULT_ARB will automatically wait (block) until the query result is actually available. A loop like

do {
glGetQueryObjectivARB(queries[i], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
} while (!available); 

is waste of time. Please read the specs :slight_smile:
To castellp:
You said, you´d do a query for every triangle of objects with more than 100000 triangles. If I understand your code correctly, that means you are creating 100k of occlusion query objects. That might be way more than your driver might be able to handle. Please plaster your code with glGetError() in order to check for possibly errors that might have occured.
I propose a slightly different approach. Create around 500 (more or less) query objects. Then start filling up a “query pipe”, e.g. render 500 triangles and start a query for each one. Then read back the result of the oldest query. You can now reuse the query object and issue a new triangle/query pair. Repeat this until you run out of triangles to be tested. At this time, there are still some queries in the pipe, read back their result one after another.

Originally posted by skynet:
[b]MickeyMouse, what you propose is nonsense. Querying for GL_QUERY_RESULT_ARB will automatically wait (block) until the query result is actually available. A loop like

do {
glGetQueryObjectivARB(queries[i], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
} while (!available); 

is waste of time. Please read the specs :slight_smile:
To castellp:
You said, you´d do a query for every triangle of objects with more than 100000 triangles. If I understand your code correctly, that means you are creating 100k of occlusion query objects. That might be way more than your driver might be able to handle. Please plaster your code with glGetError() in order to check for possibly errors that might have occured.
I propose a slightly different approach. Create around 500 (more or less) query objects. Then start filling up a “query pipe”, e.g. render 500 triangles and start a query for each one. Then read back the result of the oldest query. You can now reuse the query object and issue a new triangle/query pair. Repeat this until you run out of triangles to be tested. At this time, there are still some queries in the pipe, read back their result one after another.[/b]
Thank you, I’ve tried what you proposed but if I do more than one query it doesn’t work (I’ve tried (MAXQUERIES 100, 200, 500). Here it is my new code:

#define MAXQUERIES 100

void getSWHistoByOcclusionQuery(void) {
    GLuint i, j, v1, v2, v3, numpasses = (mesh->numTriangles / MAXQUERIES) + 1;
    GLuint end = MAXQUERIES, t;

    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
    glDepthMask(GL_FALSE);

    printf("Queries passes: %d   Multiple queries: %d
", numpasses, MAXQUERIES);

    for (j=0; j<numpasses; j++) { // Queries loop

        //printf("Query pass %d
", j);

        // This for the last pass
        if (j == (numpasses - 1)) end = mesh->numTriangles - (j * MAXQUERIES);

        for (i=0; i<end; i++) { // For every query
            glBeginQueryARB(GL_SAMPLES_PASSED_ARB, queries[i]);

            // Render triangle t
            t = (j * MAXQUERIES) + i;
            //printf("t%d
",t);

            glBegin(GL_TRIANGLES);
            ...
            glEnd();

            glEndQueryARB(GL_SAMPLES_PASSED_ARB);
        }
        glFlush();

        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
        glDepthMask(GL_TRUE);

        for (i=0; i<end; i++) { // For every query

            // triangle t
            t = (j * MAXQUERIES) + i;

            glGetQueryObjectuivARB(queries[i], GL_QUERY_RESULT_ARB, &fullHistogram[t + 1]);

            if (fullHistogram[t + 1] ==  -2029285368) { // NVIDIA value
                printf("    t:%d a:%d
", t, fullHistogram[t + 1]);
                fullHistogram[t + 1] = 0;
            }
        }
    }

    fullHistogram[0] = computeBackgroundArea(width, height, mesh->numTriangles); // Compute area of the background
} 

do {
glGetQueryObjectivARB(queries[i], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
} while (!available);
Actually this function offers you do do something useful while you’re waiting for the query result, but it makes not much sense in your example

-AnselmG

Originally posted by skynet:
[b]MickeyMouse, what you propose is nonsense. Querying for GL_QUERY_RESULT_ARB will automatically wait (block) until the query result is actually available. A loop like

do {
glGetQueryObjectivARB(queries[i], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
} while (!available); 

is waste of time. Please read the specs :slight_smile:
To castellp:
You said, you´d do a query for every triangle of objects with more than 100000 triangles. If I understand your code correctly, that means you are creating 100k of occlusion query objects. That might be way more than your driver might be able to handle. Please plaster your code with glGetError() in order to check for possibly errors that might have occured.
I propose a slightly different approach. Create around 500 (more or less) query objects. Then start filling up a “query pipe”, e.g. render 500 triangles and start a query for each one. Then read back the result of the oldest query. You can now reuse the query object and issue a new triangle/query pair. Repeat this until you run out of triangles to be tested. At this time, there are still some queries in the pipe, read back their result one after another.[/b]
Ahh, you’re right - shame on me being recently strongly influenced by Direct3D, which is a very slightly different :eek:

I thank you all, but I don’t known why it works with only one query (stop & wait) and why it doesn’t work fine with multiple queries. Im my testing the second option should be about 10 times faster. That’s why logically I want to use the second option.

glGetQueryObjectuivARB require GLuint instead of int as last parametar.

yooyo