From: Roland Scheidegger Date: Wed, 26 Jun 2013 21:11:03 +0000 (+0200) Subject: llvmpipe: add support for nested / overlapping queries X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=2e4da1f59444c550e4b1e31dd5cfec39d7ef2a26;p=mesa.git llvmpipe: add support for nested / overlapping queries 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 --- diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h index ab520019f82..9495e42feee 100644 --- a/src/gallium/drivers/llvmpipe/lp_context.h +++ b/src/gallium/drivers/llvmpipe/lp_context.h @@ -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]; diff --git a/src/gallium/drivers/llvmpipe/lp_query.c b/src/gallium/drivers/llvmpipe/lp_query.c index 38d6b84b8d7..ac6d09d9a0f 100644 --- a/src/gallium/drivers/llvmpipe/lp_query.c +++ b/src/gallium/drivers/llvmpipe/lp_query.c @@ -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: diff --git a/src/gallium/drivers/llvmpipe/lp_rast.h b/src/gallium/drivers/llvmpipe/lp_rast.h index 50917a7c633..e6e44c58262 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.h +++ b/src/gallium/drivers/llvmpipe/lp_rast.h @@ -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; diff --git a/src/gallium/drivers/llvmpipe/lp_scene.h b/src/gallium/drivers/llvmpipe/lp_scene.h index 16f69698ed0..59cce7d18f4 100644 --- a/src/gallium/drivers/llvmpipe/lp_scene.h +++ b/src/gallium/drivers/llvmpipe/lp_scene.h @@ -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() diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index d2c53255259..49aead2c1fa 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -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; + } } diff --git a/src/gallium/drivers/llvmpipe/lp_setup_context.h b/src/gallium/drivers/llvmpipe/lp_setup_context.h index cc2b97390c0..89c23bbb3ac 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_context.h +++ b/src/gallium/drivers/llvmpipe/lp_setup_context.h @@ -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; diff --git a/src/gallium/drivers/llvmpipe/lp_setup_line.c b/src/gallium/drivers/llvmpipe/lp_setup_line.c index 4b59bf38692..bfed59cba0a 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_line.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_line.c @@ -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++; } diff --git a/src/gallium/drivers/llvmpipe/lp_setup_point.c b/src/gallium/drivers/llvmpipe/lp_setup_point.c index 7fe7bc56d2b..868a9a904b7 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_point.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_point.c @@ -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++; } diff --git a/src/gallium/drivers/llvmpipe/lp_setup_tri.c b/src/gallium/drivers/llvmpipe/lp_setup_tri.c index 62df5df555f..6dc136c3aa3 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_tri.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_tri.c @@ -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++; } diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index 38e9fc7d736..6afd57a6859 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -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; }