summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/ilo
diff options
context:
space:
mode:
authorChia-I Wu <[email protected]>2012-12-13 05:35:37 +0800
committerChia-I Wu <[email protected]>2013-04-26 16:16:43 +0800
commit12dd397d0c2fb1d7015e8eb416f8903918f8f4bb (patch)
treee664444581800bec0ab82661e16bc949898d3080 /src/gallium/drivers/ilo
parente6186b0769b2a42a69ca2c5e9ef014b5961ba05d (diff)
ilo: add support for time/occlusion/primitive queries
Diffstat (limited to 'src/gallium/drivers/ilo')
-rw-r--r--src/gallium/drivers/ilo/ilo_3d.c257
-rw-r--r--src/gallium/drivers/ilo/ilo_3d.h14
-rw-r--r--src/gallium/drivers/ilo/ilo_query.c27
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
@@ -36,11 +36,214 @@
#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;
};
@@ -68,6 +73,15 @@ 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);
#endif /* ILO_3D_H */
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;