From: Iago Toral Quiroga Date: Wed, 30 Oct 2019 13:19:30 +0000 (+0100) Subject: v3d: fix primitive queries for geometry shaders X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a1b7c0844ddcbdc5ab773cbe2f6312f34111bdd9;p=mesa.git v3d: fix primitive queries for geometry shaders With geometry shaders the number of emitted primitived is decided at run time, so we cannot precompute it in the CPU and we need to use the PRIMITIVE_COUNTS_FEEDBACK commands to have the GPU provide the number like we do for the number of primitives written to transform feedback. This may have a performance impact though, since it requires a sync wait for the draw to complete, so we only do it when geometry shaders are present. v2: remove '> 0' comparison for ponter type (Alejandro) Reviewed-by: Alejandro PiƱeiro --- diff --git a/src/gallium/drivers/v3d/v3d_context.c b/src/gallium/drivers/v3d/v3d_context.c index 93f0caabc35..f3dc3a92fec 100644 --- a/src/gallium/drivers/v3d/v3d_context.c +++ b/src/gallium/drivers/v3d/v3d_context.c @@ -123,7 +123,7 @@ v3d_invalidate_resource(struct pipe_context *pctx, struct pipe_resource *prsc) * output targets. */ void -v3d_tf_update_counters(struct v3d_context *v3d) +v3d_update_primitive_counters(struct v3d_context *v3d) { struct v3d_job *job = v3d_get_job_for_fbo(v3d); if (job->draw_calls_queued == 0) diff --git a/src/gallium/drivers/v3d/v3d_context.h b/src/gallium/drivers/v3d/v3d_context.h index f8d146847de..e3a5be5fea2 100644 --- a/src/gallium/drivers/v3d/v3d_context.h +++ b/src/gallium/drivers/v3d/v3d_context.h @@ -693,7 +693,7 @@ bool v3d_generate_mipmap(struct pipe_context *pctx, struct v3d_fence *v3d_fence_create(struct v3d_context *v3d); -void v3d_tf_update_counters(struct v3d_context *v3d); +void v3d_update_primitive_counters(struct v3d_context *v3d); #ifdef v3dX # include "v3dx_context.h" diff --git a/src/gallium/drivers/v3d/v3d_job.c b/src/gallium/drivers/v3d/v3d_job.c index 0acd8b033c2..32c1157c06c 100644 --- a/src/gallium/drivers/v3d/v3d_job.c +++ b/src/gallium/drivers/v3d/v3d_job.c @@ -459,6 +459,11 @@ v3d_read_and_accumulate_primitive_counters(struct v3d_context *v3d) if (v3d_bo_wait(rsc->bo, PIPE_TIMEOUT_INFINITE, "prim-counts")) { uint32_t *map = v3d_bo_map(rsc->bo) + v3d->prim_counts_offset; v3d->tf_prims_generated += map[V3D_PRIM_COUNTS_TF_WRITTEN]; + /* When we only have a vertex shader we determine the primitive + * count in the CPU so don't update it here again. + */ + if (v3d->prog.gs) + v3d->prims_generated += map[V3D_PRIM_COUNTS_WRITTEN]; } } diff --git a/src/gallium/drivers/v3d/v3d_query.c b/src/gallium/drivers/v3d/v3d_query.c index f8419605dc2..334713e5cc5 100644 --- a/src/gallium/drivers/v3d/v3d_query.c +++ b/src/gallium/drivers/v3d/v3d_query.c @@ -72,6 +72,13 @@ v3d_begin_query(struct pipe_context *pctx, struct pipe_query *query) switch (q->type) { case PIPE_QUERY_PRIMITIVES_GENERATED: + /* If we are using PRIMITIVE_COUNTS_FEEDBACK to retrieve + * primitive counts from the GPU (which we need when a GS + * is present), then we need to update our counters now + * to discard any primitives generated before this. + */ + if (v3d->prog.gs) + v3d_update_primitive_counters(v3d); q->start = v3d->prims_generated; break; case PIPE_QUERY_PRIMITIVES_EMITTED: @@ -79,7 +86,7 @@ v3d_begin_query(struct pipe_context *pctx, struct pipe_query *query) * primitive counts to skip primtives recorded before this. */ if (v3d->streamout.num_targets > 0) - v3d_tf_update_counters(v3d); + v3d_update_primitive_counters(v3d); q->start = v3d->tf_prims_generated; break; case PIPE_QUERY_OCCLUSION_COUNTER: @@ -107,6 +114,12 @@ v3d_end_query(struct pipe_context *pctx, struct pipe_query *query) switch (q->type) { case PIPE_QUERY_PRIMITIVES_GENERATED: + /* If we are using PRIMITIVE_COUNTS_FEEDBACK to retrieve + * primitive counts from the GPU (which we need when a GS + * is present), then we need to update our counters now. + */ + if (v3d->prog.gs) + v3d_update_primitive_counters(v3d); q->end = v3d->prims_generated; break; case PIPE_QUERY_PRIMITIVES_EMITTED: @@ -115,7 +128,7 @@ v3d_end_query(struct pipe_context *pctx, struct pipe_query *query) * time. Otherwise, we have to do it now. */ if (v3d->streamout.num_targets > 0) - v3d_tf_update_counters(v3d); + v3d_update_primitive_counters(v3d); q->end = v3d->tf_prims_generated; break; case PIPE_QUERY_OCCLUSION_COUNTER: diff --git a/src/gallium/drivers/v3d/v3dx_draw.c b/src/gallium/drivers/v3d/v3dx_draw.c index 812ca3b94a7..a0714d4a02e 100644 --- a/src/gallium/drivers/v3d/v3dx_draw.c +++ b/src/gallium/drivers/v3d/v3dx_draw.c @@ -961,15 +961,18 @@ v3d_emit_gl_shader_state(struct v3d_context *v3d, } /** - * Updates the number of primitvies generated from the number of vertices - * to draw. We do this here instead of using PRIMITIVE_COUNTS_FEEDBACK because - * using the GPU packet for this might require sync waits and this is trivial - * to handle in the CPU instead. + * Updates the number of primitives generated from the number of vertices + * to draw. This only works when no GS is present, since otherwise the number + * of primitives generated cannot be determined in advance and we need to + * use the PRIMITIVE_COUNTS_FEEDBACK command instead, however, that requires + * a sync wait for the draw to complete, so we only use that when GS is present. */ static void v3d_update_primitives_generated_counter(struct v3d_context *v3d, const struct pipe_draw_info *info) { + assert(!v3d->prog.gs); + if (!v3d->active_queries) return; @@ -1131,7 +1134,7 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) */ if (v3d->streamout.num_targets > 0 && u_base_prim_type(info->mode) != u_base_prim_type(v3d->prim_mode)) { - v3d_tf_update_counters(v3d); + v3d_update_primitive_counters(v3d); } struct v3d_job *job = v3d_get_job_for_fbo(v3d); @@ -1239,7 +1242,8 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) prim_tf_enable = (V3D_PRIM_POINTS_TF - V3D_PRIM_POINTS); #endif - v3d_update_primitives_generated_counter(v3d, info); + if (!v3d->prog.gs) + v3d_update_primitives_generated_counter(v3d, info); uint32_t hw_prim_type = v3d_hw_prim_type(info->mode); if (info->index_size) { diff --git a/src/gallium/drivers/v3d/v3dx_state.c b/src/gallium/drivers/v3d/v3dx_state.c index 840d8288298..a0bb71ca540 100644 --- a/src/gallium/drivers/v3d/v3dx_state.c +++ b/src/gallium/drivers/v3d/v3dx_state.c @@ -1234,7 +1234,7 @@ v3d_set_stream_output_targets(struct pipe_context *pctx, * draw we need to do it here as well. */ if (num_targets == 0 && so->num_targets > 0) - v3d_tf_update_counters(ctx); + v3d_update_primitive_counters(ctx); for (i = 0; i < num_targets; i++) { if (offsets[i] != -1)