From c59393b7069f59ca2a13bfb6500f2a5360c38031 Mon Sep 17 00:00:00 2001 From: Paul Berry Date: Thu, 15 Dec 2011 14:57:57 -0800 Subject: [PATCH] i965 gen6: Implement transform feedback queries. This patch adds software-based PRIMITIVES_GENERATED and TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN queries that work by keeping track of the number of primitives that are sent down the pipeline, and adjusting as necessary to account for the way each primitive type is tessellated. In the long run we'll want to replace this with a hardware-based implementation, because the software approach won't work with geometry shaders or primitive restart. However, at the moment, we don't have the necessary kernel support to implement a hardware-based query (we would need the kernel to save GPU registers when context switching, so that drawing performed by another process doesn't get counted). Fixes Piglit tests EXT_transform_feedback/query-primitives_generated-* and EXT_transform_feedback/query-primitives-written-*. Reviewed-by: Kenneth Graunke --- src/mesa/drivers/dri/i965/brw_context.h | 2 + src/mesa/drivers/dri/i965/brw_draw.c | 4 ++ src/mesa/drivers/dri/i965/brw_queryobj.c | 48 ++++++++++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h index 8840a83d497..15a781b93ae 100644 --- a/src/mesa/drivers/dri/i965/brw_context.h +++ b/src/mesa/drivers/dri/i965/brw_context.h @@ -988,6 +988,8 @@ struct brw_context struct brw_sol_state { uint32_t svbi_0_starting_index; uint32_t svbi_0_max_index; + uint32_t primitives_generated; + uint32_t primitives_written; } sol; uint32_t render_target_format[MESA_FORMAT_COUNT]; diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c index 774a5ca46ee..082bb9aa24a 100644 --- a/src/mesa/drivers/dri/i965/brw_draw.c +++ b/src/mesa/drivers/dri/i965/brw_draw.c @@ -388,6 +388,7 @@ brw_update_primitive_count(struct brw_context *brw, const struct _mesa_prim *prim) { uint32_t count = count_tessellated_primitives(prim); + brw->sol.primitives_generated += count; if (brw->intel.ctx.TransformFeedback.CurrentObject->Active) { /* Update brw->sol.svbi_0_max_index to reflect the amount by which the * hardware is going to increment SVBI 0 when this drawing operation @@ -404,6 +405,9 @@ brw_update_primitive_count(struct brw_context *brw, uint32_t primitives_written = MIN2 (space_avail, count); brw->sol.svbi_0_starting_index += svbi_postincrement_value * primitives_written; + + /* And update the TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN query. */ + brw->sol.primitives_written += primitives_written; } } diff --git a/src/mesa/drivers/dri/i965/brw_queryobj.c b/src/mesa/drivers/dri/i965/brw_queryobj.c index 3ad522da138..72b83f45708 100644 --- a/src/mesa/drivers/dri/i965/brw_queryobj.c +++ b/src/mesa/drivers/dri/i965/brw_queryobj.c @@ -75,6 +75,14 @@ brw_queryobj_get_results(struct gl_context *ctx, } break; + case GL_PRIMITIVES_GENERATED: + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + /* We don't actually query the hardware for this value, so query->bo + * should always be NULL and execution should never reach here. + */ + assert(!"Unreachable"); + break; + default: assert(!"Unrecognized query target in brw_queryobj_get_results()"); break; @@ -158,6 +166,20 @@ brw_begin_query(struct gl_context *ctx, struct gl_query_object *q) intel->stats_wm++; break; + case GL_PRIMITIVES_GENERATED: + /* We don't actually query the hardware for this value; we keep track of + * it a software counter. So just reset the counter. + */ + brw->sol.primitives_generated = 0; + break; + + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + /* We don't actually query the hardware for this value; we keep track of + * it a software counter. So just reset the counter. + */ + brw->sol.primitives_written = 0; + break; + default: assert(!"Unrecognized query target in brw_begin_query()"); break; @@ -221,6 +243,32 @@ brw_end_query(struct gl_context *ctx, struct gl_query_object *q) intel->stats_wm--; break; + case GL_PRIMITIVES_GENERATED: + /* We don't actually query the hardware for this value; we keep track of + * it in a software counter. So just read the counter and store it in + * the query object. + */ + query->Base.Result = brw->sol.primitives_generated; + + /* And set brw->query.obj to NULL so that this query won't try to wait + * for any rendering to complete. + */ + query->bo = NULL; + break; + + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + /* We don't actually query the hardware for this value; we keep track of + * it in a software counter. So just read the counter and store it in + * the query object. + */ + query->Base.Result = brw->sol.primitives_written; + + /* And set brw->query.obj to NULL so that this query won't try to wait + * for any rendering to complete. + */ + query->bo = NULL; + break; + default: assert(!"Unrecognized query target in brw_end_query()"); break;