From 12dd397d0c2fb1d7015e8eb416f8903918f8f4bb Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Thu, 13 Dec 2012 05:35:37 +0800 Subject: [PATCH] ilo: add support for time/occlusion/primitive queries --- src/gallium/drivers/ilo/ilo_3d.c | 257 ++++++++++++++++++++++++++++ src/gallium/drivers/ilo/ilo_3d.h | 14 ++ src/gallium/drivers/ilo/ilo_query.c | 27 ++- 3 files changed, 293 insertions(+), 5 deletions(-) diff --git a/src/gallium/drivers/ilo/ilo_3d.c b/src/gallium/drivers/ilo/ilo_3d.c index 9d01c92def7..8d917c06b71 100644 --- a/src/gallium/drivers/ilo/ilo_3d.c +++ b/src/gallium/drivers/ilo/ilo_3d.c @@ -35,12 +35,215 @@ #include "ilo_state.h" #include "ilo_3d.h" +/** + * Begin a query. + */ +void +ilo_3d_begin_query(struct ilo_context *ilo, struct ilo_query *q) +{ + struct ilo_3d *hw3d = ilo->hw3d; + + ilo_cp_set_ring(hw3d->cp, ILO_CP_RING_RENDER); + + switch (q->type) { + case PIPE_QUERY_OCCLUSION_COUNTER: + /* reserve some space for pausing the query */ + q->reg_cmd_size = ilo_3d_pipeline_estimate_size(hw3d->pipeline, + ILO_3D_PIPELINE_WRITE_DEPTH_COUNT, NULL); + ilo_cp_reserve_for_pre_flush(hw3d->cp, q->reg_cmd_size); + + q->data.u64 = 0; + + if (ilo_query_alloc_bo(q, 2, -1, hw3d->cp->winsys)) { + /* XXX we should check the aperture size */ + ilo_3d_pipeline_emit_write_depth_count(hw3d->pipeline, + q->bo, q->reg_read++); + + list_add(&q->list, &hw3d->occlusion_queries); + } + break; + case PIPE_QUERY_TIMESTAMP: + /* nop */ + break; + case PIPE_QUERY_TIME_ELAPSED: + /* reserve some space for pausing the query */ + q->reg_cmd_size = ilo_3d_pipeline_estimate_size(hw3d->pipeline, + ILO_3D_PIPELINE_WRITE_TIMESTAMP, NULL); + ilo_cp_reserve_for_pre_flush(hw3d->cp, q->reg_cmd_size); + + q->data.u64 = 0; + + if (ilo_query_alloc_bo(q, 2, -1, hw3d->cp->winsys)) { + /* XXX we should check the aperture size */ + ilo_3d_pipeline_emit_write_timestamp(hw3d->pipeline, + q->bo, q->reg_read++); + + list_add(&q->list, &hw3d->time_elapsed_queries); + } + break; + case PIPE_QUERY_PRIMITIVES_GENERATED: + q->data.u64 = 0; + list_add(&q->list, &hw3d->prim_generated_queries); + break; + case PIPE_QUERY_PRIMITIVES_EMITTED: + q->data.u64 = 0; + list_add(&q->list, &hw3d->prim_emitted_queries); + break; + default: + assert(!"unknown query type"); + break; + } +} + +/** + * End a query. + */ +void +ilo_3d_end_query(struct ilo_context *ilo, struct ilo_query *q) +{ + struct ilo_3d *hw3d = ilo->hw3d; + + ilo_cp_set_ring(hw3d->cp, ILO_CP_RING_RENDER); + + switch (q->type) { + case PIPE_QUERY_OCCLUSION_COUNTER: + list_del(&q->list); + + assert(q->reg_read < q->reg_total); + ilo_cp_reserve_for_pre_flush(hw3d->cp, -q->reg_cmd_size); + ilo_3d_pipeline_emit_write_depth_count(hw3d->pipeline, + q->bo, q->reg_read++); + break; + case PIPE_QUERY_TIMESTAMP: + q->data.u64 = 0; + + if (ilo_query_alloc_bo(q, 1, 1, hw3d->cp->winsys)) { + ilo_3d_pipeline_emit_write_timestamp(hw3d->pipeline, + q->bo, q->reg_read++); + } + break; + case PIPE_QUERY_TIME_ELAPSED: + list_del(&q->list); + + assert(q->reg_read < q->reg_total); + ilo_cp_reserve_for_pre_flush(hw3d->cp, -q->reg_cmd_size); + ilo_3d_pipeline_emit_write_timestamp(hw3d->pipeline, + q->bo, q->reg_read++); + break; + case PIPE_QUERY_PRIMITIVES_GENERATED: + case PIPE_QUERY_PRIMITIVES_EMITTED: + list_del(&q->list); + break; + default: + assert(!"unknown query type"); + break; + } +} + +static void +process_query_for_occlusion_counter(struct ilo_3d *hw3d, + struct ilo_query *q) +{ + uint64_t *vals, depth_count = 0; + int i; + + /* in pairs */ + assert(q->reg_read % 2 == 0); + + q->bo->map(q->bo, false); + vals = q->bo->get_virtual(q->bo); + for (i = 1; i < q->reg_read; i += 2) + depth_count += vals[i] - vals[i - 1]; + q->bo->unmap(q->bo); + + /* accumulate so that the query can be resumed if wanted */ + q->data.u64 += depth_count; + q->reg_read = 0; +} + +static uint64_t +timestamp_to_ns(uint64_t timestamp) +{ + /* see ilo_get_timestamp() */ + return (timestamp & 0xffffffff) * 80; +} + +static void +process_query_for_timestamp(struct ilo_3d *hw3d, struct ilo_query *q) +{ + uint64_t *vals, timestamp; + + assert(q->reg_read == 1); + + q->bo->map(q->bo, false); + vals = q->bo->get_virtual(q->bo); + timestamp = vals[0]; + q->bo->unmap(q->bo); + + q->data.u64 = timestamp_to_ns(timestamp); + q->reg_read = 0; +} + +static void +process_query_for_time_elapsed(struct ilo_3d *hw3d, struct ilo_query *q) +{ + uint64_t *vals, elapsed = 0; + int i; + + /* in pairs */ + assert(q->reg_read % 2 == 0); + + q->bo->map(q->bo, false); + vals = q->bo->get_virtual(q->bo); + + for (i = 1; i < q->reg_read; i += 2) + elapsed += vals[i] - vals[i - 1]; + + q->bo->unmap(q->bo); + + /* accumulate so that the query can be resumed if wanted */ + q->data.u64 += timestamp_to_ns(elapsed); + q->reg_read = 0; +} + +/** + * Process the raw query data. + */ +void +ilo_3d_process_query(struct ilo_context *ilo, struct ilo_query *q) +{ + struct ilo_3d *hw3d = ilo->hw3d; + + switch (q->type) { + case PIPE_QUERY_OCCLUSION_COUNTER: + if (q->bo) + process_query_for_occlusion_counter(hw3d, q); + break; + case PIPE_QUERY_TIMESTAMP: + if (q->bo) + process_query_for_timestamp(hw3d, q); + break; + case PIPE_QUERY_TIME_ELAPSED: + if (q->bo) + process_query_for_time_elapsed(hw3d, q); + break; + case PIPE_QUERY_PRIMITIVES_GENERATED: + case PIPE_QUERY_PRIMITIVES_EMITTED: + break; + default: + assert(!"unknown query type"); + break; + } +} + /** * Hook for CP new-batch. */ void ilo_3d_new_cp_batch(struct ilo_3d *hw3d) { + struct ilo_query *q; + hw3d->new_batch = true; /* invalidate the pipeline */ @@ -51,6 +254,26 @@ ilo_3d_new_cp_batch(struct ilo_3d *hw3d) ilo_3d_pipeline_invalidate(hw3d->pipeline, ILO_3D_PIPELINE_INVALIDATE_HW); } + + /* resume occlusion queries */ + LIST_FOR_EACH_ENTRY(q, &hw3d->occlusion_queries, list) { + /* accumulate the result if the bo is alreay full */ + if (q->reg_read >= q->reg_total) + process_query_for_occlusion_counter(hw3d, q); + + ilo_3d_pipeline_emit_write_depth_count(hw3d->pipeline, + q->bo, q->reg_read++); + } + + /* resume timer queries */ + LIST_FOR_EACH_ENTRY(q, &hw3d->time_elapsed_queries, list) { + /* accumulate the result if the bo is alreay full */ + if (q->reg_read >= q->reg_total) + process_query_for_time_elapsed(hw3d, q); + + ilo_3d_pipeline_emit_write_timestamp(hw3d->pipeline, + q->bo, q->reg_read++); + } } /** @@ -59,6 +282,21 @@ ilo_3d_new_cp_batch(struct ilo_3d *hw3d) void ilo_3d_pre_cp_flush(struct ilo_3d *hw3d) { + struct ilo_query *q; + + /* pause occlusion queries */ + LIST_FOR_EACH_ENTRY(q, &hw3d->occlusion_queries, list) { + assert(q->reg_read < q->reg_total); + ilo_3d_pipeline_emit_write_depth_count(hw3d->pipeline, + q->bo, q->reg_read++); + } + + /* pause timer queries */ + LIST_FOR_EACH_ENTRY(q, &hw3d->time_elapsed_queries, list) { + assert(q->reg_read < q->reg_total); + ilo_3d_pipeline_emit_write_timestamp(hw3d->pipeline, + q->bo, q->reg_read++); + } } /** @@ -86,6 +324,11 @@ ilo_3d_create(struct ilo_cp *cp, int gen, int gt) hw3d->cp = cp; hw3d->new_batch = true; + list_inithead(&hw3d->occlusion_queries); + list_inithead(&hw3d->time_elapsed_queries); + list_inithead(&hw3d->prim_generated_queries); + list_inithead(&hw3d->prim_emitted_queries); + hw3d->pipeline = ilo_3d_pipeline_create(cp, gen, gt); if (!hw3d->pipeline) { FREE(hw3d); @@ -144,6 +387,18 @@ draw_vbo(struct ilo_3d *hw3d, const struct ilo_context *ilo, prim_generated, prim_emitted); } +static void +update_prim_count(struct ilo_3d *hw3d, int generated, int emitted) +{ + struct ilo_query *q; + + LIST_FOR_EACH_ENTRY(q, &hw3d->prim_generated_queries, list) + q->data.u64 += generated; + + LIST_FOR_EACH_ENTRY(q, &hw3d->prim_emitted_queries, list) + q->data.u64 += emitted; +} + static bool pass_render_condition(struct ilo_3d *hw3d, struct pipe_context *pipe) { @@ -211,6 +466,8 @@ ilo_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) hw3d->new_batch = false; hw3d->shader_cache_seqno = ilo->shader_cache->seqno; + update_prim_count(hw3d, prim_generated, prim_emitted); + if (ilo_debug & ILO_DEBUG_NOCACHE) ilo_3d_pipeline_emit_flush(hw3d->pipeline); } diff --git a/src/gallium/drivers/ilo/ilo_3d.h b/src/gallium/drivers/ilo/ilo_3d.h index c9b7bc9ea85..0febec883ff 100644 --- a/src/gallium/drivers/ilo/ilo_3d.h +++ b/src/gallium/drivers/ilo/ilo_3d.h @@ -49,6 +49,11 @@ struct ilo_3d { unsigned mode; } render_condition; + struct list_head occlusion_queries; + struct list_head time_elapsed_queries; + struct list_head prim_generated_queries; + struct list_head prim_emitted_queries; + struct ilo_3d_pipeline *pipeline; }; @@ -67,6 +72,15 @@ ilo_3d_pre_cp_flush(struct ilo_3d *hw3d); void ilo_3d_post_cp_flush(struct ilo_3d *hw3d); +void +ilo_3d_begin_query(struct ilo_context *ilo, struct ilo_query *q); + +void +ilo_3d_end_query(struct ilo_context *ilo, struct ilo_query *q); + +void +ilo_3d_process_query(struct ilo_context *ilo, struct ilo_query *q); + void ilo_init_3d_functions(struct ilo_context *ilo); diff --git a/src/gallium/drivers/ilo/ilo_query.c b/src/gallium/drivers/ilo/ilo_query.c index 0af8ca83338..f8d391a757c 100644 --- a/src/gallium/drivers/ilo/ilo_query.c +++ b/src/gallium/drivers/ilo/ilo_query.c @@ -27,6 +27,7 @@ #include "intel_winsys.h" +#include "ilo_3d.h" #include "ilo_context.h" #include "ilo_cp.h" #include "ilo_query.h" @@ -46,13 +47,13 @@ static const struct { } #define INFOX(prefix, desc) { desc, NULL, NULL, NULL, } - [PIPE_QUERY_OCCLUSION_COUNTER] = INFOX(ilo_3d, "occlusion counter"), + [PIPE_QUERY_OCCLUSION_COUNTER] = INFO(ilo_3d, "occlusion counter"), [PIPE_QUERY_OCCLUSION_PREDICATE] = INFOX(ilo_3d, "occlusion pred."), - [PIPE_QUERY_TIMESTAMP] = INFOX(ilo_3d, "timestamp"), + [PIPE_QUERY_TIMESTAMP] = INFO(ilo_3d, "timestamp"), [PIPE_QUERY_TIMESTAMP_DISJOINT] = INFOX(ilo_3d, "timestamp disjoint"), - [PIPE_QUERY_TIME_ELAPSED] = INFOX(ilo_3d, "time elapsed"), - [PIPE_QUERY_PRIMITIVES_GENERATED] = INFOX(ilo_3d, "primitives generated"), - [PIPE_QUERY_PRIMITIVES_EMITTED] = INFOX(ilo_3d, "primitives emitted"), + [PIPE_QUERY_TIME_ELAPSED] = INFO(ilo_3d, "time elapsed"), + [PIPE_QUERY_PRIMITIVES_GENERATED] = INFO(ilo_3d, "primitives generated"), + [PIPE_QUERY_PRIMITIVES_EMITTED] = INFO(ilo_3d, "primitives emitted"), [PIPE_QUERY_SO_STATISTICS] = INFOX(ilo_3d, "so statistics"), [PIPE_QUERY_SO_OVERFLOW_PREDICATE] = INFOX(ilo_3d, "so overflow pred."), [PIPE_QUERY_GPU_FINISHED] = INFOX(ilo_3d, "gpu finished"), @@ -74,6 +75,12 @@ ilo_create_query(struct pipe_context *pipe, unsigned query_type) struct ilo_query *q; switch (query_type) { + case PIPE_QUERY_OCCLUSION_COUNTER: + case PIPE_QUERY_TIMESTAMP: + case PIPE_QUERY_TIME_ELAPSED: + case PIPE_QUERY_PRIMITIVES_GENERATED: + case PIPE_QUERY_PRIMITIVES_EMITTED: + break; default: return NULL; } @@ -134,6 +141,16 @@ serialize_query_data(unsigned type, const union pipe_query_result *data, void *buf) { switch (type) { + case PIPE_QUERY_OCCLUSION_COUNTER: + case PIPE_QUERY_TIMESTAMP: + case PIPE_QUERY_TIME_ELAPSED: + case PIPE_QUERY_PRIMITIVES_GENERATED: + case PIPE_QUERY_PRIMITIVES_EMITTED: + { + uint64_t *r = buf; + r[0] = data->u64; + } + break; default: memset(buf, 0, sizeof(union pipe_query_result)); break; -- 2.30.2