From bdaf1858895705bbc2a8baaecb945f8b279ad07e Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Fri, 29 Oct 2021 17:56:39 +0200 Subject: [PATCH] v3d: Update prim_counts when prims generated query in flight without TF In order to implement GL_PRIMITIVES_GENERATED, v3d allocates a small resource and adds a command to the job to store the prim counts to it. However it was only doing this when TF was enabled which meant that if the query was used with a geometry shader but no TF then the query would always be zero. This patch makes the driver keep track of how many PRIMITIVES_GENERATED queries are in flight and then enable writing the prim count if its more than zero. Fix dEQP-GLES31.functional.geometry_shading.query.primitives_generated_* v2: Update CI expectations and references to fixed tests in commit log. v3: - Add comment that GL_PRIMITIVES_GENERATED query is included because OES_geometry_shader, but it is not part of OpenGL ES 3.1. (Iago) - Update Fixes to commit introducing geometry shaders. (Iago) Fixes: a1b7c084 ("v3d: fix primitive queries for geometry shaders") Signed-off-by: Neil Roberts Signed-off-by: Jose Maria Casanova Crespo Reviewed-by: Iago Toral Quiroga Part-of: --- src/broadcom/ci/v3d-rpi4-fails.txt | 5 ----- src/gallium/drivers/v3d/v3d_context.c | 14 ++++++++++++++ src/gallium/drivers/v3d/v3d_context.h | 6 ++++++ src/gallium/drivers/v3d/v3d_job.c | 22 ++++++++++++++++++---- src/gallium/drivers/v3d/v3d_query_pipe.c | 2 ++ src/gallium/drivers/v3d/v3dx_job.c | 2 +- src/gallium/drivers/v3d/v3dx_state.c | 10 ++-------- 7 files changed, 43 insertions(+), 18 deletions(-) diff --git a/src/broadcom/ci/v3d-rpi4-fails.txt b/src/broadcom/ci/v3d-rpi4-fails.txt index 4c1db5b..7fcef91 100644 --- a/src/broadcom/ci/v3d-rpi4-fails.txt +++ b/src/broadcom/ci/v3d-rpi4-fails.txt @@ -1,8 +1,3 @@ -dEQP-GLES31.functional.geometry_shading.query.primitives_generated_amplification,Fail -dEQP-GLES31.functional.geometry_shading.query.primitives_generated_instanced,Fail -dEQP-GLES31.functional.geometry_shading.query.primitives_generated_no_amplification,Fail -dEQP-GLES31.functional.geometry_shading.query.primitives_generated_partial_primitives,Fail - glx@glx-make-current,Crash glx@glx-multi-window-single-context,Fail glx@glx-multithread-buffer,Fail diff --git a/src/gallium/drivers/v3d/v3d_context.c b/src/gallium/drivers/v3d/v3d_context.c index 50a0e60..dd7928a 100644 --- a/src/gallium/drivers/v3d/v3d_context.c +++ b/src/gallium/drivers/v3d/v3d_context.c @@ -194,6 +194,20 @@ v3d_get_real_line_width(struct v3d_context *v3d) } void +v3d_ensure_prim_counts_allocated(struct v3d_context *ctx) +{ + if (ctx->prim_counts) + return; + + /* Init all 7 counters and 1 padding to 0 */ + uint32_t zeroes[8] = { 0 }; + u_upload_data(ctx->uploader, + 0, sizeof(zeroes), 32, zeroes, + &ctx->prim_counts_offset, + &ctx->prim_counts); +} + +void v3d_flag_dirty_sampler_state(struct v3d_context *v3d, enum pipe_shader_type shader) { diff --git a/src/gallium/drivers/v3d/v3d_context.h b/src/gallium/drivers/v3d/v3d_context.h index 964289c..7b3daf4 100644 --- a/src/gallium/drivers/v3d/v3d_context.h +++ b/src/gallium/drivers/v3d/v3d_context.h @@ -447,6 +447,8 @@ struct v3d_job { */ bool tf_enabled; + bool needs_primitives_generated; + /** * Current EZ state for drawing. Updated at the start of draw after * we've decided on the shader being rendered. @@ -574,6 +576,8 @@ struct v3d_context { uint32_t tf_prims_generated; uint32_t prims_generated; + uint32_t n_primitives_generated_queries_in_flight; + struct pipe_poly_stipple stipple; struct pipe_clip_state clip; struct pipe_viewport_state viewport; @@ -764,6 +768,8 @@ bool v3d_line_smoothing_enabled(struct v3d_context *v3d); float v3d_get_real_line_width(struct v3d_context *v3d); +void v3d_ensure_prim_counts_allocated(struct v3d_context *ctx); + void v3d_flag_dirty_sampler_state(struct v3d_context *v3d, enum pipe_shader_type shader); diff --git a/src/gallium/drivers/v3d/v3d_job.c b/src/gallium/drivers/v3d/v3d_job.c index 0e64624..8e62130 100644 --- a/src/gallium/drivers/v3d/v3d_job.c +++ b/src/gallium/drivers/v3d/v3d_job.c @@ -482,6 +482,16 @@ v3d_job_submit(struct v3d_context *v3d, struct v3d_job *job) if (!job->needs_flush) goto done; + /* The GL_PRIMITIVES_GENERATED query is included with + * OES_geometry_shader. + */ + job->needs_primitives_generated = + v3d->n_primitives_generated_queries_in_flight > 0 && + v3d->prog.gs; + + if (job->needs_primitives_generated) + v3d_ensure_prim_counts_allocated(v3d); + if (screen->devinfo.ver >= 41) v3d41_emit_rcl(job); else @@ -553,9 +563,11 @@ v3d_job_submit(struct v3d_context *v3d, struct v3d_job *job) } /* If we are submitting a job in the middle of transform - * feedback we need to read the primitive counts and accumulate - * them, otherwise they will be reset at the start of the next - * draw when we emit the Tile Binning Mode Configuration packet. + * feedback or there is a primitives generated query with a + * geometry shader then we need to read the primitive counts + * and accumulate them, otherwise they will be reset at the + * start of the next draw when we emit the Tile Binning Mode + * Configuration packet. * * If the job doesn't have any TF draw calls, then we know * the primitive count must be zero and we can skip stalling @@ -565,7 +577,9 @@ v3d_job_submit(struct v3d_context *v3d, struct v3d_job *job) * to us reading an obsolete (possibly non-zero) value from * the GPU counters. */ - if (v3d->streamout.num_targets && job->tf_draw_calls_queued > 0) + if (job->needs_primitives_generated || + (v3d->streamout.num_targets && + job->tf_draw_calls_queued > 0)) v3d_read_and_accumulate_primitive_counters(v3d); } diff --git a/src/gallium/drivers/v3d/v3d_query_pipe.c b/src/gallium/drivers/v3d/v3d_query_pipe.c index eafb7ec..7fdc7ac 100644 --- a/src/gallium/drivers/v3d/v3d_query_pipe.c +++ b/src/gallium/drivers/v3d/v3d_query_pipe.c @@ -69,6 +69,7 @@ v3d_begin_query_pipe(struct v3d_context *v3d, struct v3d_query *query) if (v3d->prog.gs) v3d_update_primitive_counters(v3d); pquery->start = v3d->prims_generated; + v3d->n_primitives_generated_queries_in_flight++; break; case PIPE_QUERY_PRIMITIVES_EMITTED: /* If we are inside transform feedback we need to update the @@ -109,6 +110,7 @@ v3d_end_query_pipe(struct v3d_context *v3d, struct v3d_query *query) if (v3d->prog.gs) v3d_update_primitive_counters(v3d); pquery->end = v3d->prims_generated; + v3d->n_primitives_generated_queries_in_flight--; break; case PIPE_QUERY_PRIMITIVES_EMITTED: /* If transform feedback has ended, then we have already diff --git a/src/gallium/drivers/v3d/v3dx_job.c b/src/gallium/drivers/v3d/v3dx_job.c index 40d6f16a..d48c97f 100644 --- a/src/gallium/drivers/v3d/v3dx_job.c +++ b/src/gallium/drivers/v3d/v3dx_job.c @@ -39,7 +39,7 @@ void v3dX(bcl_epilogue)(struct v3d_context *v3d, struct v3d_job *job) #endif cl_packet_length(FLUSH)); - if (job->tf_enabled) { + if (job->tf_enabled || job->needs_primitives_generated) { /* Write primitive counts to memory. */ assert(v3d->prim_counts); struct v3d_resource *rsc = diff --git a/src/gallium/drivers/v3d/v3dx_state.c b/src/gallium/drivers/v3d/v3dx_state.c index 3315421..e266588 100644 --- a/src/gallium/drivers/v3d/v3dx_state.c +++ b/src/gallium/drivers/v3d/v3dx_state.c @@ -1243,14 +1243,8 @@ v3d_set_stream_output_targets(struct pipe_context *pctx, so->num_targets = num_targets; /* Create primitive counters BO if needed */ - if (num_targets > 0 && !ctx->prim_counts) { - /* Init all 7 counters and 1 padding to 0 */ - uint32_t zeroes[8] = { 0 }; - u_upload_data(ctx->uploader, - 0, sizeof(zeroes), 32, zeroes, - &ctx->prim_counts_offset, - &ctx->prim_counts); - } + if (num_targets > 0) + v3d_ensure_prim_counts_allocated(ctx); ctx->dirty |= V3D_DIRTY_STREAMOUT; } -- 2.7.4