gallium: introduce device/driver UUID queries
[mesa.git] / src / gallium / drivers / ddebug / dd_screen.c
1 /**************************************************************************
2 *
3 * Copyright 2015 Advanced Micro Devices, Inc.
4 * Copyright 2008 VMware, Inc.
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * on the rights to use, copy, modify, merge, publish, distribute, sub
11 * license, and/or sell copies of the Software, and to permit persons to whom
12 * the Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include "dd_pipe.h"
29 #include "dd_public.h"
30 #include "util/u_memory.h"
31 #include <stdio.h>
32
33
34 static const char *
35 dd_screen_get_name(struct pipe_screen *_screen)
36 {
37 struct pipe_screen *screen = dd_screen(_screen)->screen;
38
39 return screen->get_name(screen);
40 }
41
42 static const char *
43 dd_screen_get_vendor(struct pipe_screen *_screen)
44 {
45 struct pipe_screen *screen = dd_screen(_screen)->screen;
46
47 return screen->get_vendor(screen);
48 }
49
50 static const char *
51 dd_screen_get_device_vendor(struct pipe_screen *_screen)
52 {
53 struct pipe_screen *screen = dd_screen(_screen)->screen;
54
55 return screen->get_device_vendor(screen);
56 }
57
58 static const void *
59 dd_screen_get_compiler_options(struct pipe_screen *_screen,
60 enum pipe_shader_ir ir,
61 enum pipe_shader_type shader)
62 {
63 struct pipe_screen *screen = dd_screen(_screen)->screen;
64
65 return screen->get_compiler_options(screen, ir, shader);
66 }
67
68 static struct disk_cache *
69 dd_screen_get_disk_shader_cache(struct pipe_screen *_screen)
70 {
71 struct pipe_screen *screen = dd_screen(_screen)->screen;
72
73 return screen->get_disk_shader_cache(screen);
74 }
75
76 static int
77 dd_screen_get_param(struct pipe_screen *_screen,
78 enum pipe_cap param)
79 {
80 struct pipe_screen *screen = dd_screen(_screen)->screen;
81
82 return screen->get_param(screen, param);
83 }
84
85 static float
86 dd_screen_get_paramf(struct pipe_screen *_screen,
87 enum pipe_capf param)
88 {
89 struct pipe_screen *screen = dd_screen(_screen)->screen;
90
91 return screen->get_paramf(screen, param);
92 }
93
94 static int
95 dd_screen_get_compute_param(struct pipe_screen *_screen,
96 enum pipe_shader_ir ir_type,
97 enum pipe_compute_cap param,
98 void *ret)
99 {
100 struct pipe_screen *screen = dd_screen(_screen)->screen;
101
102 return screen->get_compute_param(screen, ir_type, param, ret);
103 }
104
105 static int
106 dd_screen_get_shader_param(struct pipe_screen *_screen,
107 enum pipe_shader_type shader,
108 enum pipe_shader_cap param)
109 {
110 struct pipe_screen *screen = dd_screen(_screen)->screen;
111
112 return screen->get_shader_param(screen, shader, param);
113 }
114
115 static uint64_t
116 dd_screen_get_timestamp(struct pipe_screen *_screen)
117 {
118 struct pipe_screen *screen = dd_screen(_screen)->screen;
119
120 return screen->get_timestamp(screen);
121 }
122
123 static void dd_screen_query_memory_info(struct pipe_screen *_screen,
124 struct pipe_memory_info *info)
125 {
126 struct pipe_screen *screen = dd_screen(_screen)->screen;
127
128 return screen->query_memory_info(screen, info);
129 }
130
131 static struct pipe_context *
132 dd_screen_context_create(struct pipe_screen *_screen, void *priv,
133 unsigned flags)
134 {
135 struct dd_screen *dscreen = dd_screen(_screen);
136 struct pipe_screen *screen = dscreen->screen;
137
138 flags |= PIPE_CONTEXT_DEBUG;
139
140 return dd_context_create(dscreen,
141 screen->context_create(screen, priv, flags));
142 }
143
144 static boolean
145 dd_screen_is_format_supported(struct pipe_screen *_screen,
146 enum pipe_format format,
147 enum pipe_texture_target target,
148 unsigned sample_count,
149 unsigned tex_usage)
150 {
151 struct pipe_screen *screen = dd_screen(_screen)->screen;
152
153 return screen->is_format_supported(screen, format, target, sample_count,
154 tex_usage);
155 }
156
157 static boolean
158 dd_screen_can_create_resource(struct pipe_screen *_screen,
159 const struct pipe_resource *templat)
160 {
161 struct pipe_screen *screen = dd_screen(_screen)->screen;
162
163 return screen->can_create_resource(screen, templat);
164 }
165
166 static void
167 dd_screen_flush_frontbuffer(struct pipe_screen *_screen,
168 struct pipe_resource *resource,
169 unsigned level, unsigned layer,
170 void *context_private,
171 struct pipe_box *sub_box)
172 {
173 struct pipe_screen *screen = dd_screen(_screen)->screen;
174
175 screen->flush_frontbuffer(screen, resource, level, layer, context_private,
176 sub_box);
177 }
178
179 static int
180 dd_screen_get_driver_query_info(struct pipe_screen *_screen,
181 unsigned index,
182 struct pipe_driver_query_info *info)
183 {
184 struct pipe_screen *screen = dd_screen(_screen)->screen;
185
186 return screen->get_driver_query_info(screen, index, info);
187 }
188
189 static int
190 dd_screen_get_driver_query_group_info(struct pipe_screen *_screen,
191 unsigned index,
192 struct pipe_driver_query_group_info *info)
193 {
194 struct pipe_screen *screen = dd_screen(_screen)->screen;
195
196 return screen->get_driver_query_group_info(screen, index, info);
197 }
198
199
200 static void
201 dd_screen_get_driver_uuid(struct pipe_screen *_screen, char *uuid)
202 {
203 struct pipe_screen *screen = dd_screen(_screen)->screen;
204
205 screen->get_driver_uuid(screen, uuid);
206 }
207
208 static void
209 dd_screen_get_device_uuid(struct pipe_screen *_screen, char *uuid)
210 {
211 struct pipe_screen *screen = dd_screen(_screen)->screen;
212
213 screen->get_device_uuid(screen, uuid);
214 }
215
216 /********************************************************************
217 * resource
218 */
219
220 static struct pipe_resource *
221 dd_screen_resource_create(struct pipe_screen *_screen,
222 const struct pipe_resource *templat)
223 {
224 struct pipe_screen *screen = dd_screen(_screen)->screen;
225 struct pipe_resource *res = screen->resource_create(screen, templat);
226
227 if (!res)
228 return NULL;
229 res->screen = _screen;
230 return res;
231 }
232
233 static struct pipe_resource *
234 dd_screen_resource_from_handle(struct pipe_screen *_screen,
235 const struct pipe_resource *templ,
236 struct winsys_handle *handle,
237 unsigned usage)
238 {
239 struct pipe_screen *screen = dd_screen(_screen)->screen;
240 struct pipe_resource *res =
241 screen->resource_from_handle(screen, templ, handle, usage);
242
243 if (!res)
244 return NULL;
245 res->screen = _screen;
246 return res;
247 }
248
249 static struct pipe_resource *
250 dd_screen_resource_from_user_memory(struct pipe_screen *_screen,
251 const struct pipe_resource *templ,
252 void *user_memory)
253 {
254 struct pipe_screen *screen = dd_screen(_screen)->screen;
255 struct pipe_resource *res =
256 screen->resource_from_user_memory(screen, templ, user_memory);
257
258 if (!res)
259 return NULL;
260 res->screen = _screen;
261 return res;
262 }
263
264 static struct pipe_resource *
265 dd_screen_resource_from_memobj(struct pipe_screen *_screen,
266 const struct pipe_resource *templ,
267 struct pipe_memory_object *memobj,
268 uint64_t offset)
269 {
270 struct pipe_screen *screen = dd_screen(_screen)->screen;
271 struct pipe_resource *res =
272 screen->resource_from_memobj(screen, templ, memobj, offset);
273
274 if (!res)
275 return NULL;
276 res->screen = _screen;
277 return res;
278 }
279
280 static void
281 dd_screen_resource_changed(struct pipe_screen *_screen,
282 struct pipe_resource *res)
283 {
284 struct pipe_screen *screen = dd_screen(_screen)->screen;
285
286 screen->resource_changed(screen, res);
287 }
288
289 static void
290 dd_screen_resource_destroy(struct pipe_screen *_screen,
291 struct pipe_resource *res)
292 {
293 struct pipe_screen *screen = dd_screen(_screen)->screen;
294
295 screen->resource_destroy(screen, res);
296 }
297
298 static boolean
299 dd_screen_resource_get_handle(struct pipe_screen *_screen,
300 struct pipe_context *_pipe,
301 struct pipe_resource *resource,
302 struct winsys_handle *handle,
303 unsigned usage)
304 {
305 struct pipe_screen *screen = dd_screen(_screen)->screen;
306 struct pipe_context *pipe = _pipe ? dd_context(_pipe)->pipe : NULL;
307
308 return screen->resource_get_handle(screen, pipe, resource, handle, usage);
309 }
310
311
312 /********************************************************************
313 * fence
314 */
315
316 static void
317 dd_screen_fence_reference(struct pipe_screen *_screen,
318 struct pipe_fence_handle **pdst,
319 struct pipe_fence_handle *src)
320 {
321 struct pipe_screen *screen = dd_screen(_screen)->screen;
322
323 screen->fence_reference(screen, pdst, src);
324 }
325
326 static boolean
327 dd_screen_fence_finish(struct pipe_screen *_screen,
328 struct pipe_context *_ctx,
329 struct pipe_fence_handle *fence,
330 uint64_t timeout)
331 {
332 struct pipe_screen *screen = dd_screen(_screen)->screen;
333 struct pipe_context *ctx = _ctx ? dd_context(_ctx)->pipe : NULL;
334
335 return screen->fence_finish(screen, ctx, fence, timeout);
336 }
337
338 /********************************************************************
339 * memobj
340 */
341
342 static struct pipe_memory_object *
343 dd_screen_memobj_create_from_handle(struct pipe_screen *_screen,
344 struct winsys_handle *handle,
345 bool dedicated)
346 {
347 struct pipe_screen *screen = dd_screen(_screen)->screen;
348
349 return screen->memobj_create_from_handle(screen, handle, dedicated);
350 }
351
352 static void
353 dd_screen_memobj_destroy(struct pipe_screen *_screen,
354 struct pipe_memory_object *memobj)
355 {
356 struct pipe_screen *screen = dd_screen(_screen)->screen;
357
358 screen->memobj_destroy(screen, memobj);
359 }
360 /********************************************************************
361 * screen
362 */
363
364 static void
365 dd_screen_destroy(struct pipe_screen *_screen)
366 {
367 struct dd_screen *dscreen = dd_screen(_screen);
368 struct pipe_screen *screen = dscreen->screen;
369
370 screen->destroy(screen);
371 FREE(dscreen);
372 }
373
374 struct pipe_screen *
375 ddebug_screen_create(struct pipe_screen *screen)
376 {
377 struct dd_screen *dscreen;
378 const char *option;
379 bool no_flush;
380 unsigned timeout = 0;
381 unsigned apitrace_dump_call = 0;
382 enum dd_mode mode;
383
384 option = debug_get_option("GALLIUM_DDEBUG", NULL);
385 if (!option)
386 return screen;
387
388 if (!strcmp(option, "help")) {
389 puts("Gallium driver debugger");
390 puts("");
391 puts("Usage:");
392 puts("");
393 puts(" GALLIUM_DDEBUG=\"always [noflush] [verbose]\"");
394 puts(" Flush and dump context and driver information after every draw call into");
395 puts(" $HOME/"DD_DIR"/.");
396 puts("");
397 puts(" GALLIUM_DDEBUG=\"[timeout in ms] [noflush] [verbose]\"");
398 puts(" Flush and detect a device hang after every draw call based on the given");
399 puts(" fence timeout and dump context and driver information into");
400 puts(" $HOME/"DD_DIR"/ when a hang is detected.");
401 puts("");
402 puts(" GALLIUM_DDEBUG=\"pipelined [timeout in ms] [verbose]\"");
403 puts(" Detect a device hang after every draw call based on the given fence");
404 puts(" timeout without flushes and dump context and driver information into");
405 puts(" $HOME/"DD_DIR"/ when a hang is detected.");
406 puts("");
407 puts(" GALLIUM_DDEBUG=\"apitrace [call#] [verbose]\"");
408 puts(" Dump apitrace draw call information into $HOME/"DD_DIR"/. Implies 'noflush'.");
409 puts("");
410 puts(" If 'noflush' is specified, do not flush on every draw call. In hang");
411 puts(" detection mode, this only detect hangs in pipe->flush.");
412 puts(" If 'verbose' is specified, additional information is written to stderr.");
413 puts("");
414 puts(" GALLIUM_DDEBUG_SKIP=[count]");
415 puts(" Skip flush and hang detection for the given initial number of draw calls.");
416 puts("");
417 exit(0);
418 }
419
420 no_flush = strstr(option, "noflush") != NULL;
421
422 if (!strncmp(option, "always", 6)) {
423 mode = DD_DUMP_ALL_CALLS;
424 } else if (!strncmp(option, "apitrace", 8)) {
425 mode = DD_DUMP_APITRACE_CALL;
426 no_flush = true;
427
428 if (sscanf(option+8, "%u", &apitrace_dump_call) != 1)
429 return screen;
430 } else if (!strncmp(option, "pipelined", 9)) {
431 mode = DD_DETECT_HANGS_PIPELINED;
432
433 if (sscanf(option+10, "%u", &timeout) != 1)
434 return screen;
435 } else {
436 mode = DD_DETECT_HANGS;
437
438 if (sscanf(option, "%u", &timeout) != 1)
439 return screen;
440 }
441
442 dscreen = CALLOC_STRUCT(dd_screen);
443 if (!dscreen)
444 return NULL;
445
446 #define SCR_INIT(_member) \
447 dscreen->base._member = screen->_member ? dd_screen_##_member : NULL
448
449 dscreen->base.destroy = dd_screen_destroy;
450 dscreen->base.get_name = dd_screen_get_name;
451 dscreen->base.get_vendor = dd_screen_get_vendor;
452 dscreen->base.get_device_vendor = dd_screen_get_device_vendor;
453 SCR_INIT(get_disk_shader_cache);
454 dscreen->base.get_param = dd_screen_get_param;
455 dscreen->base.get_paramf = dd_screen_get_paramf;
456 dscreen->base.get_compute_param = dd_screen_get_compute_param;
457 dscreen->base.get_shader_param = dd_screen_get_shader_param;
458 dscreen->base.query_memory_info = dd_screen_query_memory_info;
459 /* get_video_param */
460 /* get_compute_param */
461 SCR_INIT(get_timestamp);
462 dscreen->base.context_create = dd_screen_context_create;
463 dscreen->base.is_format_supported = dd_screen_is_format_supported;
464 /* is_video_format_supported */
465 SCR_INIT(can_create_resource);
466 dscreen->base.resource_create = dd_screen_resource_create;
467 dscreen->base.resource_from_handle = dd_screen_resource_from_handle;
468 SCR_INIT(resource_from_memobj);
469 SCR_INIT(resource_from_user_memory);
470 dscreen->base.resource_get_handle = dd_screen_resource_get_handle;
471 SCR_INIT(resource_changed);
472 dscreen->base.resource_destroy = dd_screen_resource_destroy;
473 SCR_INIT(flush_frontbuffer);
474 SCR_INIT(fence_reference);
475 SCR_INIT(fence_finish);
476 SCR_INIT(memobj_create_from_handle);
477 SCR_INIT(memobj_destroy);
478 SCR_INIT(get_driver_query_info);
479 SCR_INIT(get_driver_query_group_info);
480 SCR_INIT(get_compiler_options);
481 SCR_INIT(get_driver_uuid);
482 SCR_INIT(get_device_uuid);
483
484 #undef SCR_INIT
485
486 dscreen->screen = screen;
487 dscreen->timeout_ms = timeout;
488 dscreen->mode = mode;
489 dscreen->no_flush = no_flush;
490 dscreen->verbose = strstr(option, "verbose") != NULL;
491 dscreen->apitrace_dump_call = apitrace_dump_call;
492
493 switch (dscreen->mode) {
494 case DD_DUMP_ALL_CALLS:
495 fprintf(stderr, "Gallium debugger active. Logging all calls.\n");
496 break;
497 case DD_DETECT_HANGS:
498 case DD_DETECT_HANGS_PIPELINED:
499 fprintf(stderr, "Gallium debugger active. "
500 "The hang detection timeout is %i ms.\n", timeout);
501 break;
502 case DD_DUMP_APITRACE_CALL:
503 fprintf(stderr, "Gallium debugger active. Going to dump an apitrace call.\n");
504 break;
505 default:
506 assert(0);
507 }
508
509 dscreen->skip_count = debug_get_num_option("GALLIUM_DDEBUG_SKIP", 0);
510 if (dscreen->skip_count > 0) {
511 fprintf(stderr, "Gallium debugger skipping the first %u draw calls.\n",
512 dscreen->skip_count);
513 }
514
515 return &dscreen->base;
516 }