iris: propagate error from gen_perf_begin_query to glBeginPerfQueryINTEL
[mesa.git] / src / gallium / drivers / iris / iris_performance_query.c
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
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 *
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
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
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
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
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
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
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
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
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, data_size, data, bytes_written);
218 }
219
220 void
221 iris_init_perfquery_functions(struct pipe_context *ctx)
222 {
223 ctx->init_intel_perf_query_info = iris_init_perf_query_info;
224 ctx->get_intel_perf_query_info = iris_get_perf_query_info;
225 ctx->get_intel_perf_query_counter_info = iris_get_perf_counter_info;
226 ctx->new_intel_perf_query_obj = iris_new_perf_query_obj;
227 ctx->begin_intel_perf_query = iris_begin_perf_query;
228 ctx->end_intel_perf_query = iris_end_perf_query;
229 ctx->delete_intel_perf_query = iris_delete_perf_query;
230 ctx->wait_intel_perf_query = iris_wait_perf_query;
231 ctx->is_intel_perf_query_ready = iris_is_perf_query_ready;
232 ctx->get_intel_perf_query_data = iris_get_perf_query_data;
233 }