b405703e31185789fa6b8b58b017533183b19541
[mesa.git] / src / mesa / state_tracker / st_cb_perfquery.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 /**
24 * Intel Performance query interface to gallium.
25 */
26
27 #include "st_debug.h"
28 #include "st_context.h"
29 #include "st_cb_bitmap.h"
30 #include "st_cb_perfquery.h"
31 #include "st_util.h"
32
33 #include "util/bitset.h"
34
35 #include "pipe/p_context.h"
36 #include "pipe/p_screen.h"
37 #include "util/u_memory.h"
38
39 bool
40 st_have_perfquery(struct st_context *st)
41 {
42 struct pipe_context *pipe = st->pipe;
43
44 return pipe->init_intel_perf_query_info && pipe->get_intel_perf_query_info &&
45 pipe->get_intel_perf_query_counter_info &&
46 pipe->new_intel_perf_query_obj && pipe->begin_intel_perf_query &&
47 pipe->end_intel_perf_query && pipe->delete_intel_perf_query &&
48 pipe->wait_intel_perf_query && pipe->is_intel_perf_query_ready &&
49 pipe->get_intel_perf_query_data;
50 }
51
52 static unsigned
53 st_InitPerfQueryInfo(struct gl_context *ctx)
54 {
55 struct pipe_context *pipe = st_context(ctx)->pipe;
56
57 return pipe->init_intel_perf_query_info(pipe);
58 }
59
60 static void
61 st_GetPerfQueryInfo(struct gl_context *ctx,
62 unsigned query_index,
63 const char **name,
64 GLuint *data_size,
65 GLuint *n_counters,
66 GLuint *n_active)
67 {
68 struct pipe_context *pipe = st_context(ctx)->pipe;
69
70 pipe->get_intel_perf_query_info(pipe, query_index, name, data_size,
71 n_counters, n_active);
72 }
73
74 static uint32_t
75 pipe_counter_type_enum_to_gl_type(enum pipe_perf_counter_type type)
76 {
77 switch (type) {
78 case PIPE_PERF_COUNTER_TYPE_EVENT: return GL_PERFQUERY_COUNTER_EVENT_INTEL;
79 case PIPE_PERF_COUNTER_TYPE_DURATION_NORM: return GL_PERFQUERY_COUNTER_DURATION_NORM_INTEL;
80 case PIPE_PERF_COUNTER_TYPE_DURATION_RAW: return GL_PERFQUERY_COUNTER_DURATION_RAW_INTEL;
81 case PIPE_PERF_COUNTER_TYPE_THROUGHPUT: return GL_PERFQUERY_COUNTER_THROUGHPUT_INTEL;
82 case PIPE_PERF_COUNTER_TYPE_RAW: return GL_PERFQUERY_COUNTER_RAW_INTEL;
83 case PIPE_PERF_COUNTER_TYPE_TIMESTAMP: return GL_PERFQUERY_COUNTER_TIMESTAMP_INTEL;
84 default:
85 unreachable("Unknown counter type");
86 }
87 }
88
89 static uint32_t
90 pipe_counter_data_type_to_gl_type(enum pipe_perf_counter_data_type type)
91 {
92 switch (type) {
93 case PIPE_PERF_COUNTER_DATA_TYPE_BOOL32: return GL_PERFQUERY_COUNTER_DATA_BOOL32_INTEL;
94 case PIPE_PERF_COUNTER_DATA_TYPE_UINT32: return GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL;
95 case PIPE_PERF_COUNTER_DATA_TYPE_UINT64: return GL_PERFQUERY_COUNTER_DATA_UINT64_INTEL;
96 case PIPE_PERF_COUNTER_DATA_TYPE_FLOAT: return GL_PERFQUERY_COUNTER_DATA_FLOAT_INTEL;
97 case PIPE_PERF_COUNTER_DATA_TYPE_DOUBLE: return GL_PERFQUERY_COUNTER_DATA_DOUBLE_INTEL;
98 default:
99 unreachable("Unknown counter data type");
100 }
101 }
102
103 static void
104 st_GetPerfCounterInfo(struct gl_context *ctx,
105 unsigned query_index,
106 unsigned counter_index,
107 const char **name,
108 const char **desc,
109 GLuint *offset,
110 GLuint *data_size,
111 GLuint *type_enum,
112 GLuint *data_type_enum,
113 GLuint64 *raw_max)
114 {
115 struct pipe_context *pipe = st_context(ctx)->pipe;
116 uint32_t pipe_type_enum;
117 uint32_t pipe_data_type_enum;
118
119 pipe->get_intel_perf_query_counter_info(pipe, query_index, counter_index,
120 name, desc, offset, data_size,
121 &pipe_type_enum, &pipe_data_type_enum, raw_max);
122 *type_enum = pipe_counter_type_enum_to_gl_type(pipe_type_enum);
123 *data_type_enum = pipe_counter_data_type_to_gl_type(pipe_data_type_enum);
124 }
125
126 static void
127 st_DeletePerfQuery(struct gl_context *ctx, struct gl_perf_query_object *o)
128 {
129 struct pipe_context *pipe = st_context(ctx)->pipe;
130
131 /* We can assume that the frontend waits for a query to complete
132 * before ever calling into here, so we don't have to worry about
133 * deleting an in-flight query object.
134 */
135 assert(!o->Active);
136 assert(!o->Used || o->Ready);
137
138 pipe->delete_intel_perf_query(pipe, (struct pipe_query *)o);
139 }
140
141 static bool
142 st_BeginPerfQuery(struct gl_context *ctx, struct gl_perf_query_object *o)
143 {
144 struct pipe_context *pipe = st_context(ctx)->pipe;
145
146 /* We can assume the frontend hides mistaken attempts to Begin a
147 * query object multiple times before its End. Similarly if an
148 * application reuses a query object before results have arrived
149 * the frontend will wait for prior results so we don't need
150 * to support abandoning in-flight results.
151 */
152 assert(!o->Active);
153 assert(!o->Used || o->Ready); /* no in-flight query to worry about */
154
155 pipe->begin_intel_perf_query(pipe, (struct pipe_query *)o);
156
157 return true;
158 }
159
160 static void
161 st_EndPerfQuery(struct gl_context *ctx, struct gl_perf_query_object *o)
162 {
163 struct pipe_context *pipe = st_context(ctx)->pipe;
164
165 pipe->end_intel_perf_query(pipe, (struct pipe_query *)o);
166 }
167
168 static void
169 st_WaitPerfQuery(struct gl_context *ctx, struct gl_perf_query_object *o)
170 {
171 struct pipe_context *pipe = st_context(ctx)->pipe;
172
173 assert(!o->Ready);
174
175 pipe->wait_intel_perf_query(pipe, (struct pipe_query *)o);
176 }
177
178 static bool
179 st_IsPerfQueryReady(struct gl_context *ctx, struct gl_perf_query_object *o)
180 {
181 struct pipe_context *pipe = st_context(ctx)->pipe;
182
183 if (o->Ready)
184 return true;
185
186 return pipe->is_intel_perf_query_ready(pipe, (struct pipe_query *)o);
187 }
188
189 static void
190 st_GetPerfQueryData(struct gl_context *ctx,
191 struct gl_perf_query_object *o,
192 GLsizei data_size,
193 GLuint *data,
194 GLuint *bytes_written)
195 {
196 struct pipe_context *pipe = st_context(ctx)->pipe;
197
198 assert(st_IsPerfQueryReady(ctx, o));
199
200 /* We expect that the frontend only calls this hook when it knows
201 * that results are available.
202 */
203 assert(o->Ready);
204
205 pipe->get_intel_perf_query_data(pipe, (struct pipe_query *)o, data_size, data,
206 bytes_written);
207 }
208
209 static struct gl_perf_query_object *
210 st_NewPerfQueryObject(struct gl_context *ctx, unsigned query_index)
211 {
212 struct pipe_context *pipe = st_context(ctx)->pipe;
213 struct pipe_query *q;
214
215 q = pipe->new_intel_perf_query_obj(pipe, query_index);
216
217 return (struct gl_perf_query_object *)q;
218 }
219
220 void st_init_perfquery_functions(struct dd_function_table *functions)
221 {
222 functions->InitPerfQueryInfo = st_InitPerfQueryInfo;
223 functions->GetPerfQueryInfo = st_GetPerfQueryInfo;
224 functions->GetPerfCounterInfo = st_GetPerfCounterInfo;
225 functions->NewPerfQueryObject = st_NewPerfQueryObject;
226 functions->DeletePerfQuery = st_DeletePerfQuery;
227 functions->BeginPerfQuery = st_BeginPerfQuery;
228 functions->EndPerfQuery = st_EndPerfQuery;
229 functions->WaitPerfQuery = st_WaitPerfQuery;
230 functions->IsPerfQueryReady = st_IsPerfQueryReady;
231 functions->GetPerfQueryData = st_GetPerfQueryData;
232 }