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?
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
You’re not doing anything I pointed out, nor you haven’t read the spec
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);
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
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);
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?.
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;
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
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
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
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
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.