diff options
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/drivers/ilo/ilo_query.c | 189 | ||||
-rw-r--r-- | src/gallium/drivers/ilo/ilo_query.h | 24 |
2 files changed, 208 insertions, 5 deletions
diff --git a/src/gallium/drivers/ilo/ilo_query.c b/src/gallium/drivers/ilo/ilo_query.c index bb7971d09dc..0af8ca83338 100644 --- a/src/gallium/drivers/ilo/ilo_query.c +++ b/src/gallium/drivers/ilo/ilo_query.c @@ -25,18 +25,197 @@ * Chia-I Wu <[email protected]> */ +#include "intel_winsys.h" + #include "ilo_context.h" +#include "ilo_cp.h" #include "ilo_query.h" +static const struct { + const char *name; + + void (*begin)(struct ilo_context *ilo, struct ilo_query *q); + void (*end)(struct ilo_context *ilo, struct ilo_query *q); + void (*process)(struct ilo_context *ilo, struct ilo_query *q); +} query_info[PIPE_QUERY_TYPES] = { +#define INFO(prefix, desc) { \ + .name = desc, \ + .begin = prefix ## _begin_query, \ + .end = prefix ## _end_query, \ + .process = prefix ## _process_query, \ +} +#define INFOX(prefix, desc) { desc, NULL, NULL, NULL, } + + [PIPE_QUERY_OCCLUSION_COUNTER] = INFOX(ilo_3d, "occlusion counter"), + [PIPE_QUERY_OCCLUSION_PREDICATE] = INFOX(ilo_3d, "occlusion pred."), + [PIPE_QUERY_TIMESTAMP] = INFOX(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_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"), + [PIPE_QUERY_PIPELINE_STATISTICS] = INFOX(ilo_3d, "pipeline statistics"), + +#undef INFO +#undef INFOX +}; + +static inline struct ilo_query * +ilo_query(struct pipe_query *query) +{ + return (struct ilo_query *) query; +} + +static struct pipe_query * +ilo_create_query(struct pipe_context *pipe, unsigned query_type) +{ + struct ilo_query *q; + + switch (query_type) { + default: + return NULL; + } + + q = CALLOC_STRUCT(ilo_query); + if (!q) + return NULL; + + q->type = query_type; + list_inithead(&q->list); + + return (struct pipe_query *) q; +} + +static void +ilo_destroy_query(struct pipe_context *pipe, struct pipe_query *query) +{ + struct ilo_query *q = ilo_query(query); + + if (q->bo) + q->bo->unreference(q->bo); + + FREE(q); +} + +static void +ilo_begin_query(struct pipe_context *pipe, struct pipe_query *query) +{ + struct ilo_context *ilo = ilo_context(pipe); + struct ilo_query *q = ilo_query(query); + + q->active = true; + + query_info[q->type].begin(ilo, q); +} + +static void +ilo_end_query(struct pipe_context *pipe, struct pipe_query *query) +{ + struct ilo_context *ilo = ilo_context(pipe); + struct ilo_query *q = ilo_query(query); + + query_info[q->type].end(ilo, q); + + /* + * some queries such as timestamp query does not require a call to + * begin_query() so q->active is always false + */ + q->active = false; +} + +/** + * The type (union pipe_query_result) indicates only the size of the buffer. + * Callers expect the result to be "serialized". + */ +static void +serialize_query_data(unsigned type, const union pipe_query_result *data, + void *buf) +{ + switch (type) { + default: + memset(buf, 0, sizeof(union pipe_query_result)); + break; + } +} + +static boolean +ilo_get_query_result(struct pipe_context *pipe, struct pipe_query *query, + boolean wait, union pipe_query_result *result) +{ + struct ilo_context *ilo = ilo_context(pipe); + struct ilo_query *q = ilo_query(query); + + if (q->active) + return false; + + if (q->bo) { + if (ilo->cp->bo->references(ilo->cp->bo, q->bo)) + ilo_cp_flush(ilo->cp); + + if (!wait && intel_bo_is_busy(q->bo)) + return false; + + query_info[q->type].process(ilo, q); + } + + if (result) + serialize_query_data(q->type, &q->data, (void *) result); + + return true; +} + +/** + * Allocate a query bo for reading hardware statistics. + * + * \param reg_count specifies how many registers need to be read. + * \param repeat_count specifies how many times the registers are read. If + * zero or negative, a 4KB bo is allocated. + */ +bool +ilo_query_alloc_bo(struct ilo_query *q, int reg_count, int repeat_count, + struct intel_winsys *winsys) +{ + const char *name; + int reg_total; + + name = query_info[q->type].name; + + reg_total = reg_count * repeat_count; + if (reg_total <= 0) + reg_total = 4096 / sizeof(uint64_t); + + /* (re-)allocate the bo */ + if (q->reg_total < reg_total) { + /* registers are 64-bit */ + const int size = reg_total * sizeof(uint64_t); + + if (q->bo) + q->bo->unreference(q->bo); + + q->bo = winsys->alloc_buffer(winsys, name, size, 0); + q->reg_total = (q->bo) ? reg_total : 0; + } + + /* avoid partial reads */ + if (reg_count) + q->reg_total -= q->reg_total % reg_count; + + q->reg_read = 0; + + return (q->bo != NULL); +} + /** * Initialize query-related functions. */ void ilo_init_query_functions(struct ilo_context *ilo) { - ilo->base.create_query = NULL; - ilo->base.destroy_query = NULL; - ilo->base.begin_query = NULL; - ilo->base.end_query = NULL; - ilo->base.get_query_result = NULL; + ilo->base.create_query = ilo_create_query; + ilo->base.destroy_query = ilo_destroy_query; + ilo->base.begin_query = ilo_begin_query; + ilo->base.end_query = ilo_end_query; + ilo->base.get_query_result = ilo_get_query_result; } diff --git a/src/gallium/drivers/ilo/ilo_query.h b/src/gallium/drivers/ilo/ilo_query.h index e30f7e1f283..7fedb2fbe03 100644 --- a/src/gallium/drivers/ilo/ilo_query.h +++ b/src/gallium/drivers/ilo/ilo_query.h @@ -30,9 +30,33 @@ #include "ilo_common.h" +struct intel_bo; struct ilo_context; +/** + * Queries can be bound to various places in the driver. While bound, it tells + * the driver to collect the data indicated by the type of the query. + */ +struct ilo_query { + unsigned type; + bool active; + + struct list_head list; + + /* storage for the collected data */ + union pipe_query_result data; + + /* for queries that need to read hardware statistics */ + struct intel_bo *bo; + int reg_read, reg_total; + int reg_cmd_size; /* in dwords, as expected by ilo_cp */ +}; + void ilo_init_query_functions(struct ilo_context *ilo); +bool +ilo_query_alloc_bo(struct ilo_query *q, int reg_count, int repeat_count, + struct intel_winsys *winsys); + #endif /* ILO_QUERY_H */ |