OpenGL doesn't support this but d3d10 does. It is a bit of a pain as it is necessary to keep track of queries still active at the end of a scene, which is also why I cheat a bit and limit the amount of simultaneously active queries to (arbitrary) 16 (simplifies things because don't have to deal with a real list that way). I can't think of a reason why you'd really want large numbers of overlapping/nested queries so it is hopefully fine. (This only affects queries which need to be binned.) v2: don't copy remainder of array when deleting an entry simply replace the deleted entry with the last one (order doesn't matter). Reviewed-by: Jose Fonseca <jfonseca@vmware.com>tags/mesa-9.2-rc1
@@ -97,9 +97,9 @@ struct llvmpipe_context { | |||
struct pipe_query_data_pipeline_statistics pipeline_statistics; | |||
unsigned active_statistics_queries; | |||
unsigned dirty; /**< Mask of LP_NEW_x flags */ | |||
unsigned active_occlusion_queries; | |||
unsigned active_occlusion_query; | |||
unsigned dirty; /**< Mask of LP_NEW_x flags */ | |||
/** Mapped vertex buffers */ | |||
ubyte *mapped_vbuffer[PIPE_MAX_ATTRIBS]; |
@@ -233,7 +233,7 @@ llvmpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q) | |||
break; | |||
case PIPE_QUERY_OCCLUSION_COUNTER: | |||
case PIPE_QUERY_OCCLUSION_PREDICATE: | |||
llvmpipe->active_occlusion_query++; | |||
llvmpipe->active_occlusion_queries++; | |||
llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY; | |||
break; | |||
default: | |||
@@ -288,8 +288,8 @@ llvmpipe_end_query(struct pipe_context *pipe, struct pipe_query *q) | |||
break; | |||
case PIPE_QUERY_OCCLUSION_COUNTER: | |||
case PIPE_QUERY_OCCLUSION_PREDICATE: | |||
assert(llvmpipe->active_occlusion_query); | |||
llvmpipe->active_occlusion_query--; | |||
assert(llvmpipe->active_occlusion_queries); | |||
llvmpipe->active_occlusion_queries--; | |||
llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY; | |||
break; | |||
default: |
@@ -53,6 +53,8 @@ struct cmd_bin; | |||
/* Rasterizer output size going to jit fs, width/height */ | |||
#define LP_RASTER_BLOCK_SIZE 4 | |||
#define LP_MAX_ACTIVE_BINNED_QUERIES 16 | |||
struct lp_rasterizer_task; | |||
@@ -130,7 +130,7 @@ struct lp_scene { | |||
struct lp_fence *fence; | |||
/* The queries still active at end of scene */ | |||
struct llvmpipe_query *active_queries[3]; | |||
struct llvmpipe_query *active_queries[LP_MAX_ACTIVE_BINNED_QUERIES]; | |||
unsigned num_active_queries; | |||
/* Framebuffer mappings - valid only between begin_rasterization() |
@@ -155,22 +155,9 @@ lp_setup_rasterize_scene( struct lp_setup_context *setup ) | |||
struct lp_scene *scene = setup->scene; | |||
struct llvmpipe_screen *screen = llvmpipe_screen(scene->pipe->screen); | |||
scene->num_active_queries = 0; | |||
if (setup->active_query[PIPE_QUERY_OCCLUSION_COUNTER]) { | |||
scene->active_queries[scene->num_active_queries] = | |||
setup->active_query[PIPE_QUERY_OCCLUSION_COUNTER]; | |||
scene->num_active_queries++; | |||
} | |||
if (setup->active_query[PIPE_QUERY_OCCLUSION_PREDICATE]) { | |||
scene->active_queries[scene->num_active_queries] = | |||
setup->active_query[PIPE_QUERY_OCCLUSION_PREDICATE]; | |||
scene->num_active_queries++; | |||
} | |||
if (setup->active_query[PIPE_QUERY_PIPELINE_STATISTICS]) { | |||
scene->active_queries[scene->num_active_queries] = | |||
setup->active_query[PIPE_QUERY_PIPELINE_STATISTICS]; | |||
scene->num_active_queries++; | |||
} | |||
scene->num_active_queries = setup->active_binned_queries; | |||
memcpy(scene->active_queries, setup->active_queries, | |||
scene->num_active_queries * sizeof(scene->active_queries[0])); | |||
lp_scene_end_binning(scene); | |||
@@ -1226,9 +1213,14 @@ lp_setup_begin_query(struct lp_setup_context *setup, | |||
return; | |||
/* init the query to its beginning state */ | |||
assert(setup->active_query[pq->type] == NULL); | |||
setup->active_query[pq->type] = pq; | |||
assert(setup->active_binned_queries < LP_MAX_ACTIVE_BINNED_QUERIES); | |||
/* exceeding list size so just ignore the query */ | |||
if (setup->active_binned_queries >= LP_MAX_ACTIVE_BINNED_QUERIES) { | |||
return; | |||
} | |||
assert(setup->active_queries[setup->active_binned_queries] == NULL); | |||
setup->active_queries[setup->active_binned_queries] = pq; | |||
setup->active_binned_queries++; | |||
assert(setup->scene); | |||
if (setup->scene) { | |||
@@ -1257,12 +1249,6 @@ lp_setup_end_query(struct lp_setup_context *setup, struct llvmpipe_query *pq) | |||
{ | |||
set_scene_state(setup, SETUP_ACTIVE, "end_query"); | |||
if (pq->type == PIPE_QUERY_OCCLUSION_COUNTER || | |||
pq->type == PIPE_QUERY_OCCLUSION_PREDICATE || | |||
pq->type == PIPE_QUERY_PIPELINE_STATISTICS) { | |||
assert(setup->active_query[pq->type] == pq); | |||
} | |||
assert(setup->scene); | |||
if (setup->scene) { | |||
/* pq->fence should be the fence of the *last* scene which | |||
@@ -1296,7 +1282,23 @@ fail: | |||
/* Need to do this now not earlier since it still needs to be marked as | |||
* active when binning it would cause a flush. | |||
*/ | |||
setup->active_query[pq->type] = NULL; | |||
if (pq->type == PIPE_QUERY_OCCLUSION_COUNTER || | |||
pq->type == PIPE_QUERY_OCCLUSION_PREDICATE || | |||
pq->type == PIPE_QUERY_PIPELINE_STATISTICS) { | |||
unsigned i; | |||
/* remove from active binned query list */ | |||
for (i = 0; i < setup->active_binned_queries; i++) { | |||
if (setup->active_queries[i] == pq) | |||
break; | |||
} | |||
assert(i < setup->active_binned_queries); | |||
if (i == setup->active_binned_queries) | |||
return; | |||
setup->active_binned_queries--; | |||
setup->active_queries[i] = setup->active_queries[setup->active_binned_queries]; | |||
setup->active_queries[setup->active_binned_queries] = NULL; | |||
} | |||
} | |||
@@ -89,7 +89,8 @@ struct lp_setup_context | |||
struct lp_scene *scene; /**< current scene being built */ | |||
struct lp_fence *last_fence; | |||
struct llvmpipe_query *active_query[PIPE_QUERY_TYPES]; | |||
struct llvmpipe_query *active_queries[LP_MAX_ACTIVE_BINNED_QUERIES]; | |||
unsigned active_binned_queries; | |||
boolean subdivide_large_triangles; | |||
boolean flatshade_first; |
@@ -278,6 +278,7 @@ try_setup_line( struct lp_setup_context *setup, | |||
const float (*v1)[4], | |||
const float (*v2)[4]) | |||
{ | |||
struct llvmpipe_context *lp_context = (struct llvmpipe_context *)setup->pipe; | |||
struct lp_scene *scene = setup->scene; | |||
const struct lp_setup_variant_key *key = &setup->setup.variant->key; | |||
struct lp_rast_triangle *line; | |||
@@ -596,8 +597,7 @@ try_setup_line( struct lp_setup_context *setup, | |||
LP_COUNT(nr_tris); | |||
if (setup->active_query[PIPE_QUERY_PIPELINE_STATISTICS]) { | |||
struct llvmpipe_context *lp_context = (struct llvmpipe_context *)setup->pipe; | |||
if (lp_context->active_statistics_queries) { | |||
lp_context->pipeline_statistics.c_primitives++; | |||
} | |||
@@ -303,6 +303,7 @@ static boolean | |||
try_setup_point( struct lp_setup_context *setup, | |||
const float (*v0)[4] ) | |||
{ | |||
struct llvmpipe_context *lp_context = (struct llvmpipe_context *)setup->pipe; | |||
/* x/y positions in fixed point */ | |||
const struct lp_setup_variant_key *key = &setup->setup.variant->key; | |||
const int sizeAttr = setup->psize; | |||
@@ -379,8 +380,7 @@ try_setup_point( struct lp_setup_context *setup, | |||
LP_COUNT(nr_tris); | |||
if (setup->active_query[PIPE_QUERY_PIPELINE_STATISTICS]) { | |||
struct llvmpipe_context *lp_context = (struct llvmpipe_context *)setup->pipe; | |||
if (lp_context->active_statistics_queries) { | |||
lp_context->pipeline_statistics.c_primitives++; | |||
} | |||
@@ -252,6 +252,7 @@ do_triangle_ccw(struct lp_setup_context *setup, | |||
const float (*v2)[4], | |||
boolean frontfacing ) | |||
{ | |||
struct llvmpipe_context *lp_context = (struct llvmpipe_context *)setup->pipe; | |||
struct lp_scene *scene = setup->scene; | |||
const struct lp_setup_variant_key *key = &setup->setup.variant->key; | |||
struct lp_rast_triangle *tri; | |||
@@ -339,8 +340,7 @@ do_triangle_ccw(struct lp_setup_context *setup, | |||
LP_COUNT(nr_tris); | |||
if (setup->active_query[PIPE_QUERY_PIPELINE_STATISTICS]) { | |||
struct llvmpipe_context *lp_context = (struct llvmpipe_context *)setup->pipe; | |||
if (lp_context->active_statistics_queries) { | |||
lp_context->pipeline_statistics.c_primitives++; | |||
} | |||
@@ -2630,7 +2630,7 @@ make_variant_key(struct llvmpipe_context *lp, | |||
/* alpha.ref_value is passed in jit_context */ | |||
key->flatshade = lp->rasterizer->flatshade; | |||
if (lp->active_occlusion_query) { | |||
if (lp->active_occlusion_queries) { | |||
key->occlusion_count = TRUE; | |||
} | |||