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 <ctype.h>
32#include <stdio.h>
33
34
35static const char *
36dd_screen_get_name(struct pipe_screen *_screen)
37{
38   struct pipe_screen *screen = dd_screen(_screen)->screen;
39
40   return screen->get_name(screen);
41}
42
43static const char *
44dd_screen_get_vendor(struct pipe_screen *_screen)
45{
46   struct pipe_screen *screen = dd_screen(_screen)->screen;
47
48   return screen->get_vendor(screen);
49}
50
51static const char *
52dd_screen_get_device_vendor(struct pipe_screen *_screen)
53{
54   struct pipe_screen *screen = dd_screen(_screen)->screen;
55
56   return screen->get_device_vendor(screen);
57}
58
59static const void *
60dd_screen_get_compiler_options(struct pipe_screen *_screen,
61                               enum pipe_shader_ir ir,
62                               enum pipe_shader_type shader)
63{
64   struct pipe_screen *screen = dd_screen(_screen)->screen;
65
66   return screen->get_compiler_options(screen, ir, shader);
67}
68
69static struct disk_cache *
70dd_screen_get_disk_shader_cache(struct pipe_screen *_screen)
71{
72   struct pipe_screen *screen = dd_screen(_screen)->screen;
73
74   return screen->get_disk_shader_cache(screen);
75}
76
77static int
78dd_screen_get_param(struct pipe_screen *_screen,
79                    enum pipe_cap param)
80{
81   struct pipe_screen *screen = dd_screen(_screen)->screen;
82
83   return screen->get_param(screen, param);
84}
85
86static float
87dd_screen_get_paramf(struct pipe_screen *_screen,
88                     enum pipe_capf param)
89{
90   struct pipe_screen *screen = dd_screen(_screen)->screen;
91
92   return screen->get_paramf(screen, param);
93}
94
95static int
96dd_screen_get_compute_param(struct pipe_screen *_screen,
97                            enum pipe_shader_ir ir_type,
98                            enum pipe_compute_cap param,
99                            void *ret)
100{
101   struct pipe_screen *screen = dd_screen(_screen)->screen;
102
103   return screen->get_compute_param(screen, ir_type, param, ret);
104}
105
106static int
107dd_screen_get_shader_param(struct pipe_screen *_screen,
108                           enum pipe_shader_type shader,
109                           enum pipe_shader_cap param)
110{
111   struct pipe_screen *screen = dd_screen(_screen)->screen;
112
113   return screen->get_shader_param(screen, shader, param);
114}
115
116static uint64_t
117dd_screen_get_timestamp(struct pipe_screen *_screen)
118{
119   struct pipe_screen *screen = dd_screen(_screen)->screen;
120
121   return screen->get_timestamp(screen);
122}
123
124static void dd_screen_query_memory_info(struct pipe_screen *_screen,
125                                        struct pipe_memory_info *info)
126{
127   struct pipe_screen *screen = dd_screen(_screen)->screen;
128
129   screen->query_memory_info(screen, info);
130}
131
132static struct pipe_context *
133dd_screen_context_create(struct pipe_screen *_screen, void *priv,
134                         unsigned flags)
135{
136   struct dd_screen *dscreen = dd_screen(_screen);
137   struct pipe_screen *screen = dscreen->screen;
138
139   flags |= PIPE_CONTEXT_DEBUG;
140
141   return dd_context_create(dscreen,
142                            screen->context_create(screen, priv, flags));
143}
144
145static bool
146dd_screen_is_format_supported(struct pipe_screen *_screen,
147                              enum pipe_format format,
148                              enum pipe_texture_target target,
149                              unsigned sample_count,
150                              unsigned storage_sample_count,
151                              unsigned tex_usage)
152{
153   struct pipe_screen *screen = dd_screen(_screen)->screen;
154
155   return screen->is_format_supported(screen, format, target, sample_count,
156                                      storage_sample_count, tex_usage);
157}
158
159static bool
160dd_screen_can_create_resource(struct pipe_screen *_screen,
161                              const struct pipe_resource *templat)
162{
163   struct pipe_screen *screen = dd_screen(_screen)->screen;
164
165   return screen->can_create_resource(screen, templat);
166}
167
168static void
169dd_screen_flush_frontbuffer(struct pipe_screen *_screen,
170                            struct pipe_context *_pipe,
171                            struct pipe_resource *resource,
172                            unsigned level, unsigned layer,
173                            void *context_private,
174                            struct pipe_box *sub_box)
175{
176   struct pipe_screen *screen = dd_screen(_screen)->screen;
177   struct pipe_context *pipe = _pipe ? dd_context(_pipe)->pipe : NULL;
178
179   screen->flush_frontbuffer(screen, pipe, resource, level, layer, context_private,
180                             sub_box);
181}
182
183static int
184dd_screen_get_driver_query_info(struct pipe_screen *_screen,
185                                unsigned index,
186                                struct pipe_driver_query_info *info)
187{
188   struct pipe_screen *screen = dd_screen(_screen)->screen;
189
190   return screen->get_driver_query_info(screen, index, info);
191}
192
193static int
194dd_screen_get_driver_query_group_info(struct pipe_screen *_screen,
195                                      unsigned index,
196                                      struct pipe_driver_query_group_info *info)
197{
198   struct pipe_screen *screen = dd_screen(_screen)->screen;
199
200   return screen->get_driver_query_group_info(screen, index, info);
201}
202
203
204static void
205dd_screen_get_driver_uuid(struct pipe_screen *_screen, char *uuid)
206{
207   struct pipe_screen *screen = dd_screen(_screen)->screen;
208
209   screen->get_driver_uuid(screen, uuid);
210}
211
212static void
213dd_screen_get_device_uuid(struct pipe_screen *_screen, char *uuid)
214{
215   struct pipe_screen *screen = dd_screen(_screen)->screen;
216
217   screen->get_device_uuid(screen, uuid);
218}
219
220/********************************************************************
221 * resource
222 */
223
224static struct pipe_resource *
225dd_screen_resource_create(struct pipe_screen *_screen,
226                          const struct pipe_resource *templat)
227{
228   struct pipe_screen *screen = dd_screen(_screen)->screen;
229   struct pipe_resource *res = screen->resource_create(screen, templat);
230
231   if (!res)
232      return NULL;
233   res->screen = _screen;
234   return res;
235}
236
237static struct pipe_resource *
238dd_screen_resource_from_handle(struct pipe_screen *_screen,
239                               const struct pipe_resource *templ,
240                               struct winsys_handle *handle,
241                               unsigned usage)
242{
243   struct pipe_screen *screen = dd_screen(_screen)->screen;
244   struct pipe_resource *res =
245      screen->resource_from_handle(screen, templ, handle, usage);
246
247   if (!res)
248      return NULL;
249   res->screen = _screen;
250   return res;
251}
252
253static struct pipe_resource *
254dd_screen_resource_from_user_memory(struct pipe_screen *_screen,
255                                    const struct pipe_resource *templ,
256                                    void *user_memory)
257{
258   struct pipe_screen *screen = dd_screen(_screen)->screen;
259   struct pipe_resource *res =
260      screen->resource_from_user_memory(screen, templ, user_memory);
261
262   if (!res)
263      return NULL;
264   res->screen = _screen;
265   return res;
266}
267
268static struct pipe_resource *
269dd_screen_resource_from_memobj(struct pipe_screen *_screen,
270                               const struct pipe_resource *templ,
271                               struct pipe_memory_object *memobj,
272                               uint64_t offset)
273{
274   struct pipe_screen *screen = dd_screen(_screen)->screen;
275   struct pipe_resource *res =
276      screen->resource_from_memobj(screen, templ, memobj, offset);
277
278   if (!res)
279      return NULL;
280   res->screen = _screen;
281   return res;
282}
283
284static void
285dd_screen_resource_changed(struct pipe_screen *_screen,
286                           struct pipe_resource *res)
287{
288   struct pipe_screen *screen = dd_screen(_screen)->screen;
289
290   if (screen->resource_changed)
291      screen->resource_changed(screen, res);
292}
293
294static void
295dd_screen_resource_destroy(struct pipe_screen *_screen,
296                           struct pipe_resource *res)
297{
298   struct pipe_screen *screen = dd_screen(_screen)->screen;
299
300   screen->resource_destroy(screen, res);
301}
302
303static bool
304dd_screen_resource_get_handle(struct pipe_screen *_screen,
305                              struct pipe_context *_pipe,
306                              struct pipe_resource *resource,
307                              struct winsys_handle *handle,
308                              unsigned usage)
309{
310   struct pipe_screen *screen = dd_screen(_screen)->screen;
311   struct pipe_context *pipe = _pipe ? dd_context(_pipe)->pipe : NULL;
312
313   return screen->resource_get_handle(screen, pipe, resource, handle, usage);
314}
315
316static bool
317dd_screen_resource_get_param(struct pipe_screen *_screen,
318                             struct pipe_context *_pipe,
319                             struct pipe_resource *resource,
320                             unsigned plane,
321                             unsigned layer,
322                             unsigned level,
323                             enum pipe_resource_param param,
324                             unsigned handle_usage,
325                             uint64_t *value)
326{
327   struct pipe_screen *screen = dd_screen(_screen)->screen;
328   struct pipe_context *pipe = _pipe ? dd_context(_pipe)->pipe : NULL;
329
330   return screen->resource_get_param(screen, pipe, resource, plane, layer,
331                                     level, param, handle_usage, value);
332}
333
334static void
335dd_screen_resource_get_info(struct pipe_screen *_screen,
336                            struct pipe_resource *resource,
337                            unsigned *stride,
338                            unsigned *offset)
339{
340   struct pipe_screen *screen = dd_screen(_screen)->screen;
341
342   screen->resource_get_info(screen, resource, stride, offset);
343}
344
345static bool
346dd_screen_check_resource_capability(struct pipe_screen *_screen,
347                                    struct pipe_resource *resource,
348                                    unsigned bind)
349{
350   struct pipe_screen *screen = dd_screen(_screen)->screen;
351
352   return screen->check_resource_capability(screen, resource, bind);
353}
354
355
356/********************************************************************
357 * fence
358 */
359
360static void
361dd_screen_fence_reference(struct pipe_screen *_screen,
362                          struct pipe_fence_handle **pdst,
363                          struct pipe_fence_handle *src)
364{
365   struct pipe_screen *screen = dd_screen(_screen)->screen;
366
367   screen->fence_reference(screen, pdst, src);
368}
369
370static bool
371dd_screen_fence_finish(struct pipe_screen *_screen,
372                       struct pipe_context *_ctx,
373                       struct pipe_fence_handle *fence,
374                       uint64_t timeout)
375{
376   struct pipe_screen *screen = dd_screen(_screen)->screen;
377   struct pipe_context *ctx = _ctx ? dd_context(_ctx)->pipe : NULL;
378
379   return screen->fence_finish(screen, ctx, fence, timeout);
380}
381
382static int
383dd_screen_fence_get_fd(struct pipe_screen *_screen,
384                       struct pipe_fence_handle *fence)
385{
386   struct pipe_screen *screen = dd_screen(_screen)->screen;
387
388   return screen->fence_get_fd(screen, fence);
389}
390
391/********************************************************************
392 * memobj
393 */
394
395static struct pipe_memory_object *
396dd_screen_memobj_create_from_handle(struct pipe_screen *_screen,
397                                    struct winsys_handle *handle,
398                                    bool dedicated)
399{
400   struct pipe_screen *screen = dd_screen(_screen)->screen;
401
402   return screen->memobj_create_from_handle(screen, handle, dedicated);
403}
404
405static void
406dd_screen_memobj_destroy(struct pipe_screen *_screen,
407                         struct pipe_memory_object *memobj)
408{
409   struct pipe_screen *screen = dd_screen(_screen)->screen;
410
411   screen->memobj_destroy(screen, memobj);
412}
413/********************************************************************
414 * screen
415 */
416
417static char *
418dd_screen_finalize_nir(struct pipe_screen *_screen, void *nir)
419{
420   struct pipe_screen *screen = dd_screen(_screen)->screen;
421
422   return screen->finalize_nir(screen, nir);
423}
424
425static void
426dd_screen_destroy(struct pipe_screen *_screen)
427{
428   struct dd_screen *dscreen = dd_screen(_screen);
429   struct pipe_screen *screen = dscreen->screen;
430
431   screen->destroy(screen);
432   FREE(dscreen);
433}
434
435static void
436skip_space(const char **p)
437{
438   while (isspace(**p))
439      (*p)++;
440}
441
442static bool
443match_word(const char **cur, const char *word)
444{
445   size_t len = strlen(word);
446   if (strncmp(*cur, word, len) != 0)
447      return false;
448
449   const char *p = *cur + len;
450   if (*p) {
451      if (!isspace(*p))
452         return false;
453
454      *cur = p + 1;
455   } else {
456      *cur = p;
457   }
458
459   return true;
460}
461
462static bool
463match_uint(const char **cur, unsigned *value)
464{
465   char *end;
466   unsigned v = strtoul(*cur, &end, 0);
467   if (end == *cur || (*end && !isspace(*end)))
468      return false;
469   *cur = end;
470   *value = v;
471   return true;
472}
473
474struct pipe_screen *
475ddebug_screen_create(struct pipe_screen *screen)
476{
477   struct dd_screen *dscreen;
478   const char *option;
479   bool flush = false;
480   bool verbose = false;
481   bool transfers = false;
482   unsigned timeout = 1000;
483   unsigned apitrace_dump_call = 0;
484   enum dd_dump_mode mode = DD_DUMP_ONLY_HANGS;
485
486   option = debug_get_option("GALLIUM_DDEBUG", NULL);
487   if (!option)
488      return screen;
489
490   if (!strcmp(option, "help")) {
491      puts("Gallium driver debugger");
492      puts("");
493      puts("Usage:");
494      puts("");
495      puts("  GALLIUM_DDEBUG=\"[<timeout in ms>] [(always|apitrace <call#)] [flush] [transfers] [verbose]\"");
496      puts("  GALLIUM_DDEBUG_SKIP=[count]");
497      puts("");
498      puts("Dump context and driver information of draw calls into");
499      puts("$HOME/"DD_DIR"/. By default, watch for GPU hangs and only dump information");
500      puts("about draw calls related to the hang.");
501      puts("");
502      puts("<timeout in ms>");
503      puts("  Change the default timeout for GPU hang detection (default=1000ms).");
504      puts("  Setting this to 0 will disable GPU hang detection entirely.");
505      puts("");
506      puts("always");
507      puts("  Dump information about all draw calls.");
508      puts("");
509      puts("transfers");
510      puts("  Also dump and do hang detection on transfers.");
511      puts("");
512      puts("apitrace <call#>");
513      puts("  Dump information about the draw call corresponding to the given");
514      puts("  apitrace call number and exit.");
515      puts("");
516      puts("flush");
517      puts("  Flush after every draw call.");
518      puts("");
519      puts("verbose");
520      puts("  Write additional information to stderr.");
521      puts("");
522      puts("GALLIUM_DDEBUG_SKIP=count");
523      puts("  Skip dumping on the first count draw calls (only relevant with 'always').");
524      puts("");
525      exit(0);
526   }
527
528   for (;;) {
529      skip_space(&option);
530      if (!*option)
531         break;
532
533      if (match_word(&option, "always")) {
534         if (mode == DD_DUMP_APITRACE_CALL) {
535            printf("ddebug: both 'always' and 'apitrace' specified\n");
536            exit(1);
537         }
538
539         mode = DD_DUMP_ALL_CALLS;
540      } else if (match_word(&option, "flush")) {
541         flush = true;
542      } else if (match_word(&option, "transfers")) {
543         transfers = true;
544      } else if (match_word(&option, "verbose")) {
545         verbose = true;
546      } else if (match_word(&option, "apitrace")) {
547         if (mode != DD_DUMP_ONLY_HANGS) {
548            printf("ddebug: 'apitrace' can only appear once and not mixed with 'always'\n");
549            exit(1);
550         }
551
552         if (!match_uint(&option, &apitrace_dump_call)) {
553            printf("ddebug: expected call number after 'apitrace'\n");
554            exit(1);
555         }
556
557         mode = DD_DUMP_APITRACE_CALL;
558      } else if (match_uint(&option, &timeout)) {
559         /* no-op */
560      } else {
561         printf("ddebug: bad options: %s\n", option);
562         exit(1);
563      }
564   }
565
566   dscreen = CALLOC_STRUCT(dd_screen);
567   if (!dscreen)
568      return NULL;
569
570#define SCR_INIT(_member) \
571   dscreen->base._member = screen->_member ? dd_screen_##_member : NULL
572
573   dscreen->base.destroy = dd_screen_destroy;
574   dscreen->base.get_name = dd_screen_get_name;
575   dscreen->base.get_vendor = dd_screen_get_vendor;
576   dscreen->base.get_device_vendor = dd_screen_get_device_vendor;
577   SCR_INIT(get_disk_shader_cache);
578   dscreen->base.get_param = dd_screen_get_param;
579   dscreen->base.get_paramf = dd_screen_get_paramf;
580   dscreen->base.get_compute_param = dd_screen_get_compute_param;
581   dscreen->base.get_shader_param = dd_screen_get_shader_param;
582   dscreen->base.query_memory_info = dd_screen_query_memory_info;
583   /* get_video_param */
584   /* get_compute_param */
585   SCR_INIT(get_timestamp);
586   dscreen->base.context_create = dd_screen_context_create;
587   dscreen->base.is_format_supported = dd_screen_is_format_supported;
588   /* is_video_format_supported */
589   SCR_INIT(can_create_resource);
590   dscreen->base.resource_create = dd_screen_resource_create;
591   dscreen->base.resource_from_handle = dd_screen_resource_from_handle;
592   SCR_INIT(resource_from_memobj);
593   SCR_INIT(resource_from_user_memory);
594   SCR_INIT(check_resource_capability);
595   dscreen->base.resource_get_handle = dd_screen_resource_get_handle;
596   SCR_INIT(resource_get_param);
597   SCR_INIT(resource_get_info);
598   SCR_INIT(resource_changed);
599   dscreen->base.resource_destroy = dd_screen_resource_destroy;
600   SCR_INIT(flush_frontbuffer);
601   SCR_INIT(fence_reference);
602   SCR_INIT(fence_finish);
603   SCR_INIT(fence_get_fd);
604   SCR_INIT(memobj_create_from_handle);
605   SCR_INIT(memobj_destroy);
606   SCR_INIT(get_driver_query_info);
607   SCR_INIT(get_driver_query_group_info);
608   SCR_INIT(get_compiler_options);
609   SCR_INIT(get_driver_uuid);
610   SCR_INIT(get_device_uuid);
611   SCR_INIT(finalize_nir);
612
613#undef SCR_INIT
614
615   dscreen->screen = screen;
616   dscreen->timeout_ms = timeout;
617   dscreen->dump_mode = mode;
618   dscreen->flush_always = flush;
619   dscreen->transfers = transfers;
620   dscreen->verbose = verbose;
621   dscreen->apitrace_dump_call = apitrace_dump_call;
622
623   switch (dscreen->dump_mode) {
624   case DD_DUMP_ALL_CALLS:
625      fprintf(stderr, "Gallium debugger active. Logging all calls.\n");
626      break;
627   case DD_DUMP_APITRACE_CALL:
628      fprintf(stderr, "Gallium debugger active. Going to dump an apitrace call.\n");
629      break;
630   default:
631      fprintf(stderr, "Gallium debugger active.\n");
632      break;
633   }
634
635   if (dscreen->timeout_ms > 0)
636      fprintf(stderr, "Hang detection timeout is %ums.\n", dscreen->timeout_ms);
637   else
638      fprintf(stderr, "Hang detection is disabled.\n");
639
640   dscreen->skip_count = debug_get_num_option("GALLIUM_DDEBUG_SKIP", 0);
641   if (dscreen->skip_count > 0) {
642      fprintf(stderr, "Gallium debugger skipping the first %u draw calls.\n",
643              dscreen->skip_count);
644   }
645
646   return &dscreen->base;
647}
648