iris: INTEL performance query implementation
low-level implementation of INTEL-performance-query APIs in
Intel iris driver. Most of functions and procedures defined here
are adopted from i965 driver (brw_performance_query.c)
v2: - replace genX_init_performance_query with
iris_init_perfquery_functions which is gen's version agnositic
- general code clean-up
v3: include gen_perf_gens.h as some of defines were moved to this new
header file
v4: - checking for kernel 4.13+ won't be needed here as Iris won't be
loaded anyway without DRM_SYNCOBJ that is enabled after Kernel
4.13.
- checking whether gen < 8 or is_cherryview won't be required as
well because those cases are screened in iris_screen_create.
v5: remove genX(init_performance_query)
v6: - remove oa_metrics_kernel_support as iris works only with kernel
4.18 and newer.
- use perf functions defined in separate file, iris_perf.h/c
Signed-off-by: Dongwon Kim <dongwon.kim@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
This commit is contained in:
committed by
Kenneth Graunke
parent
ca2dd99bf6
commit
8a8534a698
@@ -45,6 +45,7 @@ IRIS_C_SOURCES = \
|
||||
iris_genx_macros.h \
|
||||
iris_genx_protos.h \
|
||||
iris_monitor.c \
|
||||
iris_performance_query.c \
|
||||
iris_perf.c \
|
||||
iris_pipe.h \
|
||||
iris_pipe_control.c \
|
||||
|
||||
@@ -272,6 +272,7 @@ iris_create_context(struct pipe_screen *pscreen, void *priv, unsigned flags)
|
||||
iris_init_program_functions(ctx);
|
||||
iris_init_resource_functions(ctx);
|
||||
iris_init_flush_functions(ctx);
|
||||
iris_init_perfquery_functions(ctx);
|
||||
|
||||
iris_init_program_cache(ice);
|
||||
iris_init_border_color_pool(ice);
|
||||
|
||||
@@ -767,6 +767,7 @@ void iris_init_blit_functions(struct pipe_context *ctx);
|
||||
void iris_init_clear_functions(struct pipe_context *ctx);
|
||||
void iris_init_program_functions(struct pipe_context *ctx);
|
||||
void iris_init_resource_functions(struct pipe_context *ctx);
|
||||
void iris_init_perfquery_functions(struct pipe_context *ctx);
|
||||
void iris_update_compiled_shaders(struct iris_context *ice);
|
||||
void iris_update_compiled_compute_shader(struct iris_context *ice);
|
||||
void iris_fill_cs_push_const_buffer(struct brw_cs_prog_data *cs_prog_data,
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* Copyright © 2019 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <xf86drm.h>
|
||||
|
||||
#include "iris_context.h"
|
||||
#include "iris_perf.h"
|
||||
|
||||
#include "perf/gen_perf.h"
|
||||
#include "perf/gen_perf_regs.h"
|
||||
|
||||
struct iris_perf_query {
|
||||
struct gl_perf_query_object base;
|
||||
struct gen_perf_query_object *query;
|
||||
};
|
||||
|
||||
static unsigned
|
||||
iris_init_perf_query_info(struct pipe_context *pipe)
|
||||
{
|
||||
struct iris_context *ice = (void *) pipe;
|
||||
struct iris_screen *screen = (struct iris_screen *) ice->ctx.screen;
|
||||
struct gen_perf_config *perf_cfg = NULL;
|
||||
|
||||
/* make sure pipe perf counter type/data-type enums are matched with gen_perf's */
|
||||
STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_EVENT == (enum pipe_perf_counter_type)GEN_PERF_COUNTER_TYPE_EVENT);
|
||||
STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_DURATION_NORM == (enum pipe_perf_counter_type)GEN_PERF_COUNTER_TYPE_DURATION_NORM);
|
||||
STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_DURATION_RAW == (enum pipe_perf_counter_type)GEN_PERF_COUNTER_TYPE_DURATION_RAW);
|
||||
STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_THROUGHPUT == (enum pipe_perf_counter_type)GEN_PERF_COUNTER_TYPE_THROUGHPUT);
|
||||
STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_RAW == (enum pipe_perf_counter_type)GEN_PERF_COUNTER_TYPE_RAW);
|
||||
|
||||
STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_BOOL32 == (enum pipe_perf_counter_data_type)GEN_PERF_COUNTER_DATA_TYPE_BOOL32);
|
||||
STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_UINT32 == (enum pipe_perf_counter_data_type)GEN_PERF_COUNTER_DATA_TYPE_UINT32);
|
||||
STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_UINT64 == (enum pipe_perf_counter_data_type)GEN_PERF_COUNTER_DATA_TYPE_UINT64);
|
||||
STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_FLOAT == (enum pipe_perf_counter_data_type)GEN_PERF_COUNTER_DATA_TYPE_FLOAT);
|
||||
STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_DOUBLE == (enum pipe_perf_counter_data_type)GEN_PERF_COUNTER_DATA_TYPE_DOUBLE);
|
||||
|
||||
if (!ice->perf_ctx)
|
||||
ice->perf_ctx = gen_perf_new_context(ice);
|
||||
|
||||
if (unlikely(!ice->perf_ctx))
|
||||
return 0;
|
||||
|
||||
perf_cfg = gen_perf_config(ice->perf_ctx);
|
||||
|
||||
if (perf_cfg)
|
||||
return perf_cfg->n_queries;
|
||||
|
||||
perf_cfg = gen_perf_new(ice->perf_ctx);
|
||||
|
||||
iris_perf_init_vtbl(perf_cfg);
|
||||
|
||||
gen_perf_init_context(ice->perf_ctx,
|
||||
perf_cfg,
|
||||
ice,
|
||||
screen->bufmgr,
|
||||
&screen->devinfo,
|
||||
ice->batches[IRIS_BATCH_RENDER].hw_ctx_id,
|
||||
screen->fd);
|
||||
|
||||
gen_perf_init_metrics(perf_cfg, &screen->devinfo, screen->fd);
|
||||
|
||||
return perf_cfg->n_queries;
|
||||
}
|
||||
|
||||
static struct pipe_query *
|
||||
iris_new_perf_query_obj(struct pipe_context *pipe, unsigned query_index)
|
||||
{
|
||||
struct iris_context *ice = (void *) pipe;
|
||||
struct gen_perf_context *perf_ctx = ice->perf_ctx;
|
||||
struct gen_perf_query_object * obj = gen_perf_new_query(perf_ctx, query_index);
|
||||
if (unlikely(!obj))
|
||||
return NULL;
|
||||
|
||||
struct iris_perf_query *q = calloc(1, sizeof(struct iris_perf_query));
|
||||
if (unlikely(!q)) {
|
||||
gen_perf_delete_query(perf_ctx, obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
q->query = obj;
|
||||
return (struct pipe_query *)&q->base;
|
||||
}
|
||||
|
||||
static void
|
||||
iris_begin_perf_query(struct pipe_context *pipe, struct pipe_query *q)
|
||||
{
|
||||
struct iris_context *ice = (void *) pipe;
|
||||
struct iris_perf_query *perf_query= (struct iris_perf_query *) q;
|
||||
struct gen_perf_query_object *obj = perf_query->query;
|
||||
struct gen_perf_context *perf_ctx = ice->perf_ctx;
|
||||
|
||||
gen_perf_begin_query(perf_ctx, obj);
|
||||
}
|
||||
|
||||
static void
|
||||
iris_end_perf_query(struct pipe_context *pipe, struct pipe_query *q)
|
||||
{
|
||||
struct iris_context *ice = (void *) pipe;
|
||||
struct iris_perf_query *perf_query = (struct iris_perf_query *) q;
|
||||
struct gen_perf_query_object *obj = perf_query->query;
|
||||
struct gen_perf_context *perf_ctx = ice->perf_ctx;
|
||||
|
||||
gen_perf_end_query(perf_ctx, obj);
|
||||
}
|
||||
|
||||
static void
|
||||
iris_delete_perf_query(struct pipe_context *pipe, struct pipe_query *q)
|
||||
{
|
||||
struct iris_context *ice = (void *) pipe;
|
||||
struct iris_perf_query *perf_query = (struct iris_perf_query *) q;
|
||||
struct gen_perf_query_object *obj = perf_query->query;
|
||||
struct gen_perf_context *perf_ctx = ice->perf_ctx;
|
||||
|
||||
gen_perf_delete_query(perf_ctx, obj);
|
||||
free(q);
|
||||
}
|
||||
|
||||
static void
|
||||
iris_get_perf_query_info(struct pipe_context *pipe,
|
||||
unsigned query_index,
|
||||
const char **name,
|
||||
uint32_t *data_size,
|
||||
uint32_t *n_counters,
|
||||
uint32_t *n_active)
|
||||
{
|
||||
struct iris_context *ice = (void *) pipe;
|
||||
struct gen_perf_context *perf_ctx = ice->perf_ctx;
|
||||
struct gen_perf_config *perf_cfg = gen_perf_config(perf_ctx);
|
||||
const struct gen_perf_query_info *info = &perf_cfg->queries[query_index];
|
||||
|
||||
*name = info->name;
|
||||
*data_size = info->data_size;
|
||||
*n_counters = info->n_counters;
|
||||
*n_active = gen_perf_active_queries(perf_ctx, info);
|
||||
}
|
||||
|
||||
static void
|
||||
iris_get_perf_counter_info(struct pipe_context *pipe,
|
||||
unsigned query_index,
|
||||
unsigned counter_index,
|
||||
const char **name,
|
||||
const char **desc,
|
||||
uint32_t *offset,
|
||||
uint32_t *data_size,
|
||||
uint32_t *type_enum,
|
||||
uint32_t *data_type_enum,
|
||||
uint64_t *raw_max)
|
||||
{
|
||||
struct iris_context *ice = (void *) pipe;
|
||||
struct gen_perf_context *perf_ctx = ice->perf_ctx;
|
||||
struct gen_perf_config *perf_cfg = gen_perf_config(perf_ctx);
|
||||
const struct gen_perf_query_info *info = &perf_cfg->queries[query_index];
|
||||
const struct gen_perf_query_counter *counter = &info->counters[counter_index];
|
||||
|
||||
*name = counter->name;
|
||||
*desc = counter->desc;
|
||||
*offset = counter->offset;
|
||||
*data_size = gen_perf_query_counter_get_size(counter);
|
||||
*type_enum = counter->type;
|
||||
*data_type_enum = counter->data_type;
|
||||
*raw_max = counter->raw_max;
|
||||
}
|
||||
|
||||
static void
|
||||
iris_wait_perf_query(struct pipe_context *pipe, struct pipe_query *q)
|
||||
{
|
||||
struct iris_context *ice = (void *) pipe;
|
||||
struct iris_perf_query *perf_query = (struct iris_perf_query *) q;
|
||||
struct gen_perf_query_object *obj = perf_query->query;
|
||||
struct gen_perf_context *perf_ctx = ice->perf_ctx;
|
||||
|
||||
gen_perf_wait_query(perf_ctx, obj, &ice->batches[IRIS_BATCH_RENDER]);
|
||||
}
|
||||
|
||||
static bool
|
||||
iris_is_perf_query_ready(struct pipe_context *pipe, struct pipe_query *q)
|
||||
{
|
||||
struct iris_context *ice = (void *) pipe;
|
||||
struct iris_perf_query *perf_query = (struct iris_perf_query *) q;
|
||||
struct gen_perf_query_object *obj = perf_query->query;
|
||||
struct gen_perf_context *perf_ctx = ice->perf_ctx;
|
||||
|
||||
if (perf_query->base.Ready)
|
||||
return true;
|
||||
|
||||
return gen_perf_is_query_ready(perf_ctx, obj, &ice->batches[IRIS_BATCH_RENDER]);
|
||||
}
|
||||
|
||||
static void
|
||||
iris_get_perf_query_data(struct pipe_context *pipe,
|
||||
struct pipe_query *q,
|
||||
size_t data_size,
|
||||
uint32_t *data,
|
||||
uint32_t *bytes_written)
|
||||
{
|
||||
struct iris_context *ice = (void *) pipe;
|
||||
struct iris_perf_query *perf_query = (struct iris_perf_query *) q;
|
||||
struct gen_perf_query_object *obj = perf_query->query;
|
||||
struct gen_perf_context *perf_ctx = ice->perf_ctx;
|
||||
|
||||
gen_perf_get_query_data(perf_ctx, obj, data_size, data, bytes_written);
|
||||
}
|
||||
|
||||
void
|
||||
iris_init_perfquery_functions(struct pipe_context *ctx)
|
||||
{
|
||||
ctx->init_intel_perf_query_info = iris_init_perf_query_info;
|
||||
ctx->get_intel_perf_query_info = iris_get_perf_query_info;
|
||||
ctx->get_intel_perf_query_counter_info = iris_get_perf_counter_info;
|
||||
ctx->new_intel_perf_query_obj = iris_new_perf_query_obj;
|
||||
ctx->begin_intel_perf_query = iris_begin_perf_query;
|
||||
ctx->end_intel_perf_query = iris_end_perf_query;
|
||||
ctx->delete_intel_perf_query = iris_delete_perf_query;
|
||||
ctx->wait_intel_perf_query = iris_wait_perf_query;
|
||||
ctx->is_intel_perf_query_ready = iris_is_perf_query_ready;
|
||||
ctx->get_intel_perf_query_data = iris_get_perf_query_data;
|
||||
}
|
||||
@@ -40,6 +40,7 @@ files_libiris = files(
|
||||
'iris_perf.h',
|
||||
'iris_perf.c',
|
||||
'iris_monitor.c',
|
||||
'iris_performance_query.c',
|
||||
'iris_pipe.h',
|
||||
'iris_pipe_control.c',
|
||||
'iris_program.c',
|
||||
|
||||
Reference in New Issue
Block a user