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 <nroberts@igalia.com>
Signed-off-by: Jose Maria Casanova Crespo <jmcasanova@igalia.com>
Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13712>
-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
}
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)
{
*/
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.
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;
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);
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
}
/* 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
* 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);
}
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
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
#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 =
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;
}