• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2019 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22 
23 #include <xf86drm.h>
24 
25 #include "iris_context.h"
26 #include "iris_perf.h"
27 
28 struct iris_perf_query {
29    struct gl_perf_query_object base;
30    struct gen_perf_query_object *query;
31 };
32 
33 static unsigned
iris_init_perf_query_info(struct pipe_context * pipe)34 iris_init_perf_query_info(struct pipe_context *pipe)
35 {
36    struct iris_context *ice = (void *) pipe;
37    struct iris_screen *screen = (struct iris_screen *) ice->ctx.screen;
38    struct gen_perf_config *perf_cfg = NULL;
39 
40    /* make sure pipe perf counter type/data-type enums are matched with gen_perf's */
41    STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_EVENT == (enum pipe_perf_counter_type)GEN_PERF_COUNTER_TYPE_EVENT);
42    STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_DURATION_NORM == (enum pipe_perf_counter_type)GEN_PERF_COUNTER_TYPE_DURATION_NORM);
43    STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_DURATION_RAW == (enum pipe_perf_counter_type)GEN_PERF_COUNTER_TYPE_DURATION_RAW);
44    STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_THROUGHPUT == (enum pipe_perf_counter_type)GEN_PERF_COUNTER_TYPE_THROUGHPUT);
45    STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_RAW == (enum pipe_perf_counter_type)GEN_PERF_COUNTER_TYPE_RAW);
46 
47    STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_BOOL32 == (enum pipe_perf_counter_data_type)GEN_PERF_COUNTER_DATA_TYPE_BOOL32);
48    STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_UINT32 == (enum pipe_perf_counter_data_type)GEN_PERF_COUNTER_DATA_TYPE_UINT32);
49    STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_UINT64 == (enum pipe_perf_counter_data_type)GEN_PERF_COUNTER_DATA_TYPE_UINT64);
50    STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_FLOAT == (enum pipe_perf_counter_data_type)GEN_PERF_COUNTER_DATA_TYPE_FLOAT);
51    STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_DOUBLE == (enum pipe_perf_counter_data_type)GEN_PERF_COUNTER_DATA_TYPE_DOUBLE);
52 
53    if (!ice->perf_ctx)
54       ice->perf_ctx = gen_perf_new_context(ice);
55 
56    if (unlikely(!ice->perf_ctx))
57       return 0;
58 
59    perf_cfg = gen_perf_config(ice->perf_ctx);
60 
61    if (perf_cfg)
62       return perf_cfg->n_queries;
63 
64    perf_cfg = gen_perf_new(ice->perf_ctx);
65 
66    iris_perf_init_vtbl(perf_cfg);
67 
68    gen_perf_init_context(ice->perf_ctx,
69                          perf_cfg,
70                          ice,
71                          screen->bufmgr,
72                          &screen->devinfo,
73                          ice->batches[IRIS_BATCH_RENDER].hw_ctx_id,
74                          screen->fd);
75 
76    gen_perf_init_metrics(perf_cfg, &screen->devinfo, screen->fd, true /* pipeline_statistics */);
77 
78    return perf_cfg->n_queries;
79 }
80 
81 static struct pipe_query *
iris_new_perf_query_obj(struct pipe_context * pipe,unsigned query_index)82 iris_new_perf_query_obj(struct pipe_context *pipe, unsigned query_index)
83 {
84    struct iris_context *ice = (void *) pipe;
85    struct gen_perf_context *perf_ctx = ice->perf_ctx;
86    struct gen_perf_query_object * obj = gen_perf_new_query(perf_ctx, query_index);
87    if (unlikely(!obj))
88       return NULL;
89 
90    struct iris_perf_query *q = calloc(1, sizeof(struct iris_perf_query));
91    if (unlikely(!q)) {
92       gen_perf_delete_query(perf_ctx, obj);
93       return NULL;
94    }
95 
96    q->query = obj;
97    return (struct pipe_query *)&q->base;
98 }
99 
100 static bool
iris_begin_perf_query(struct pipe_context * pipe,struct pipe_query * q)101 iris_begin_perf_query(struct pipe_context *pipe, struct pipe_query *q)
102 {
103    struct iris_context *ice = (void *) pipe;
104    struct iris_perf_query *perf_query= (struct iris_perf_query *) q;
105    struct gen_perf_query_object *obj = perf_query->query;
106    struct gen_perf_context *perf_ctx = ice->perf_ctx;
107 
108    return gen_perf_begin_query(perf_ctx, obj);
109 }
110 
111 static void
iris_end_perf_query(struct pipe_context * pipe,struct pipe_query * q)112 iris_end_perf_query(struct pipe_context *pipe, struct pipe_query *q)
113 {
114    struct iris_context *ice = (void *) pipe;
115    struct iris_perf_query *perf_query = (struct iris_perf_query *) q;
116    struct gen_perf_query_object *obj = perf_query->query;
117    struct gen_perf_context *perf_ctx = ice->perf_ctx;
118 
119    gen_perf_end_query(perf_ctx, obj);
120 }
121 
122 static void
iris_delete_perf_query(struct pipe_context * pipe,struct pipe_query * q)123 iris_delete_perf_query(struct pipe_context *pipe, struct pipe_query *q)
124 {
125    struct iris_context *ice = (void *) pipe;
126    struct iris_perf_query *perf_query = (struct iris_perf_query *) q;
127    struct gen_perf_query_object *obj = perf_query->query;
128    struct gen_perf_context *perf_ctx = ice->perf_ctx;
129 
130    gen_perf_delete_query(perf_ctx, obj);
131    free(q);
132 }
133 
134 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)135 iris_get_perf_query_info(struct pipe_context *pipe,
136                          unsigned query_index,
137                          const char **name,
138                          uint32_t *data_size,
139                          uint32_t *n_counters,
140                          uint32_t *n_active)
141 {
142    struct iris_context *ice = (void *) pipe;
143    struct gen_perf_context *perf_ctx = ice->perf_ctx;
144    struct gen_perf_config *perf_cfg = gen_perf_config(perf_ctx);
145    const struct gen_perf_query_info *info = &perf_cfg->queries[query_index];
146 
147    *name = info->name;
148    *data_size = info->data_size;
149    *n_counters = info->n_counters;
150    *n_active = gen_perf_active_queries(perf_ctx, info);
151 }
152 
153 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)154 iris_get_perf_counter_info(struct pipe_context *pipe,
155                            unsigned query_index,
156                            unsigned counter_index,
157                            const char **name,
158                            const char **desc,
159                            uint32_t *offset,
160                            uint32_t *data_size,
161                            uint32_t *type_enum,
162                            uint32_t *data_type_enum,
163                            uint64_t *raw_max)
164 {
165    struct iris_context *ice = (void *) pipe;
166    struct gen_perf_context *perf_ctx = ice->perf_ctx;
167    struct gen_perf_config *perf_cfg = gen_perf_config(perf_ctx);
168    const struct gen_perf_query_info *info = &perf_cfg->queries[query_index];
169    const struct gen_perf_query_counter *counter = &info->counters[counter_index];
170 
171    *name = counter->name;
172    *desc = counter->desc;
173    *offset = counter->offset;
174    *data_size = gen_perf_query_counter_get_size(counter);
175    *type_enum = counter->type;
176    *data_type_enum = counter->data_type;
177    *raw_max = counter->raw_max;
178 }
179 
180 static void
iris_wait_perf_query(struct pipe_context * pipe,struct pipe_query * q)181 iris_wait_perf_query(struct pipe_context *pipe, struct pipe_query *q)
182 {
183    struct iris_context *ice = (void *) pipe;
184    struct iris_perf_query *perf_query = (struct iris_perf_query *) q;
185    struct gen_perf_query_object *obj = perf_query->query;
186    struct gen_perf_context *perf_ctx = ice->perf_ctx;
187 
188    gen_perf_wait_query(perf_ctx, obj, &ice->batches[IRIS_BATCH_RENDER]);
189 }
190 
191 static bool
iris_is_perf_query_ready(struct pipe_context * pipe,struct pipe_query * q)192 iris_is_perf_query_ready(struct pipe_context *pipe, struct pipe_query *q)
193 {
194    struct iris_context *ice = (void *) pipe;
195    struct iris_perf_query *perf_query = (struct iris_perf_query *) q;
196    struct gen_perf_query_object *obj = perf_query->query;
197    struct gen_perf_context *perf_ctx = ice->perf_ctx;
198 
199    if (perf_query->base.Ready)
200       return true;
201 
202    return gen_perf_is_query_ready(perf_ctx, obj, &ice->batches[IRIS_BATCH_RENDER]);
203 }
204 
205 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)206 iris_get_perf_query_data(struct pipe_context *pipe,
207                          struct pipe_query *q,
208                          size_t data_size,
209                          uint32_t *data,
210                          uint32_t *bytes_written)
211 {
212    struct iris_context *ice = (void *) pipe;
213    struct iris_perf_query *perf_query = (struct iris_perf_query *) q;
214    struct gen_perf_query_object *obj = perf_query->query;
215    struct gen_perf_context *perf_ctx = ice->perf_ctx;
216 
217    gen_perf_get_query_data(perf_ctx, obj, &ice->batches[IRIS_BATCH_RENDER],
218          data_size, data, bytes_written);
219 }
220 
221 void
iris_init_perfquery_functions(struct pipe_context * ctx)222 iris_init_perfquery_functions(struct pipe_context *ctx)
223 {
224    ctx->init_intel_perf_query_info = iris_init_perf_query_info;
225    ctx->get_intel_perf_query_info = iris_get_perf_query_info;
226    ctx->get_intel_perf_query_counter_info = iris_get_perf_counter_info;
227    ctx->new_intel_perf_query_obj = iris_new_perf_query_obj;
228    ctx->begin_intel_perf_query = iris_begin_perf_query;
229    ctx->end_intel_perf_query = iris_end_perf_query;
230    ctx->delete_intel_perf_query = iris_delete_perf_query;
231    ctx->wait_intel_perf_query = iris_wait_perf_query;
232    ctx->is_intel_perf_query_ready = iris_is_perf_query_ready;
233    ctx->get_intel_perf_query_data = iris_get_perf_query_data;
234 }
235