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
| struct pipe_query_data_pipeline_statistics pipeline_statistics; | struct pipe_query_data_pipeline_statistics pipeline_statistics; | ||||
| unsigned active_statistics_queries; | 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 */ | /** Mapped vertex buffers */ | ||||
| ubyte *mapped_vbuffer[PIPE_MAX_ATTRIBS]; | ubyte *mapped_vbuffer[PIPE_MAX_ATTRIBS]; |
| break; | break; | ||||
| case PIPE_QUERY_OCCLUSION_COUNTER: | case PIPE_QUERY_OCCLUSION_COUNTER: | ||||
| case PIPE_QUERY_OCCLUSION_PREDICATE: | case PIPE_QUERY_OCCLUSION_PREDICATE: | ||||
| llvmpipe->active_occlusion_query++; | |||||
| llvmpipe->active_occlusion_queries++; | |||||
| llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY; | llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY; | ||||
| break; | break; | ||||
| default: | default: | ||||
| break; | break; | ||||
| case PIPE_QUERY_OCCLUSION_COUNTER: | case PIPE_QUERY_OCCLUSION_COUNTER: | ||||
| case PIPE_QUERY_OCCLUSION_PREDICATE: | 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; | llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY; | ||||
| break; | break; | ||||
| default: | default: |
| /* Rasterizer output size going to jit fs, width/height */ | /* Rasterizer output size going to jit fs, width/height */ | ||||
| #define LP_RASTER_BLOCK_SIZE 4 | #define LP_RASTER_BLOCK_SIZE 4 | ||||
| #define LP_MAX_ACTIVE_BINNED_QUERIES 16 | |||||
| struct lp_rasterizer_task; | struct lp_rasterizer_task; | ||||
| struct lp_fence *fence; | struct lp_fence *fence; | ||||
| /* The queries still active at end of scene */ | /* 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; | unsigned num_active_queries; | ||||
| /* Framebuffer mappings - valid only between begin_rasterization() | /* Framebuffer mappings - valid only between begin_rasterization() |
| struct lp_scene *scene = setup->scene; | struct lp_scene *scene = setup->scene; | ||||
| struct llvmpipe_screen *screen = llvmpipe_screen(scene->pipe->screen); | 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); | lp_scene_end_binning(scene); | ||||
| return; | return; | ||||
| /* init the query to its beginning state */ | /* 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); | assert(setup->scene); | ||||
| if (setup->scene) { | if (setup->scene) { | ||||
| { | { | ||||
| set_scene_state(setup, SETUP_ACTIVE, "end_query"); | 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); | assert(setup->scene); | ||||
| if (setup->scene) { | if (setup->scene) { | ||||
| /* pq->fence should be the fence of the *last* scene which | /* pq->fence should be the fence of the *last* scene which | ||||
| /* Need to do this now not earlier since it still needs to be marked as | /* Need to do this now not earlier since it still needs to be marked as | ||||
| * active when binning it would cause a flush. | * 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; | |||||
| } | |||||
| } | } | ||||
| struct lp_scene *scene; /**< current scene being built */ | struct lp_scene *scene; /**< current scene being built */ | ||||
| struct lp_fence *last_fence; | 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 subdivide_large_triangles; | ||||
| boolean flatshade_first; | boolean flatshade_first; |
| const float (*v1)[4], | const float (*v1)[4], | ||||
| const float (*v2)[4]) | const float (*v2)[4]) | ||||
| { | { | ||||
| struct llvmpipe_context *lp_context = (struct llvmpipe_context *)setup->pipe; | |||||
| struct lp_scene *scene = setup->scene; | struct lp_scene *scene = setup->scene; | ||||
| const struct lp_setup_variant_key *key = &setup->setup.variant->key; | const struct lp_setup_variant_key *key = &setup->setup.variant->key; | ||||
| struct lp_rast_triangle *line; | struct lp_rast_triangle *line; | ||||
| LP_COUNT(nr_tris); | 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++; | lp_context->pipeline_statistics.c_primitives++; | ||||
| } | } | ||||
| try_setup_point( struct lp_setup_context *setup, | try_setup_point( struct lp_setup_context *setup, | ||||
| const float (*v0)[4] ) | const float (*v0)[4] ) | ||||
| { | { | ||||
| struct llvmpipe_context *lp_context = (struct llvmpipe_context *)setup->pipe; | |||||
| /* x/y positions in fixed point */ | /* x/y positions in fixed point */ | ||||
| const struct lp_setup_variant_key *key = &setup->setup.variant->key; | const struct lp_setup_variant_key *key = &setup->setup.variant->key; | ||||
| const int sizeAttr = setup->psize; | const int sizeAttr = setup->psize; | ||||
| LP_COUNT(nr_tris); | 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++; | lp_context->pipeline_statistics.c_primitives++; | ||||
| } | } | ||||
| const float (*v2)[4], | const float (*v2)[4], | ||||
| boolean frontfacing ) | boolean frontfacing ) | ||||
| { | { | ||||
| struct llvmpipe_context *lp_context = (struct llvmpipe_context *)setup->pipe; | |||||
| struct lp_scene *scene = setup->scene; | struct lp_scene *scene = setup->scene; | ||||
| const struct lp_setup_variant_key *key = &setup->setup.variant->key; | const struct lp_setup_variant_key *key = &setup->setup.variant->key; | ||||
| struct lp_rast_triangle *tri; | struct lp_rast_triangle *tri; | ||||
| LP_COUNT(nr_tris); | 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++; | lp_context->pipeline_statistics.c_primitives++; | ||||
| } | } | ||||
| /* alpha.ref_value is passed in jit_context */ | /* alpha.ref_value is passed in jit_context */ | ||||
| key->flatshade = lp->rasterizer->flatshade; | key->flatshade = lp->rasterizer->flatshade; | ||||
| if (lp->active_occlusion_query) { | |||||
| if (lp->active_occlusion_queries) { | |||||
| key->occlusion_count = TRUE; | key->occlusion_count = TRUE; | ||||
| } | } | ||||