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
355static int
356dd_screen_get_sparse_texture_virtual_page_size(struct pipe_screen *_screen,
357                                               enum pipe_texture_target target,
358                                               bool multi_sample,
359                                               enum pipe_format format,
360                                               unsigned offset, unsigned size,
361                                               int *x, int *y, int *z)
362{
363   struct pipe_screen *screen = dd_screen(_screen)->screen;
364
365   return screen->get_sparse_texture_virtual_page_size(
366      _screen, target, multi_sample, format, offset, size, x, y, z);
367}
368
369/********************************************************************
370 * fence
371 */
372
373static void
374dd_screen_fence_reference(struct pipe_screen *_screen,
375                          struct pipe_fence_handle **pdst,
376                          struct pipe_fence_handle *src)
377{
378   struct pipe_screen *screen = dd_screen(_screen)->screen;
379
380   screen->fence_reference(screen, pdst, src);
381}
382
383static bool
384dd_screen_fence_finish(struct pipe_screen *_screen,
385                       struct pipe_context *_ctx,
386                       struct pipe_fence_handle *fence,
387                       uint64_t timeout)
388{
389   struct pipe_screen *screen = dd_screen(_screen)->screen;
390   struct pipe_context *ctx = _ctx ? dd_context(_ctx)->pipe : NULL;
391
392   return screen->fence_finish(screen, ctx, fence, timeout);
393}
394
395static int
396dd_screen_fence_get_fd(struct pipe_screen *_screen,
397                       struct pipe_fence_handle *fence)
398{
399   struct pipe_screen *screen = dd_screen(_screen)->screen;
400
401   return screen->fence_get_fd(screen, fence);
402}
403
404/********************************************************************
405 * vertex state
406 */
407
408static struct pipe_vertex_state *
409dd_screen_create_vertex_state(struct pipe_screen *_screen,
410                              struct pipe_vertex_buffer *buffer,
411                              const struct pipe_vertex_element *elements,
412                              unsigned num_elements,
413                              struct pipe_resource *indexbuf,
414                              uint32_t full_velem_mask)
415{
416   struct pipe_screen *screen = dd_screen(_screen)->screen;
417   struct pipe_vertex_state *state =
418      screen->create_vertex_state(screen, buffer, elements, num_elements,
419                                  indexbuf, full_velem_mask);
420
421   if (!state)
422      return NULL;
423   state->screen = _screen;
424   return state;
425}
426
427static void
428dd_screen_vertex_state_destroy(struct pipe_screen *_screen,
429                               struct pipe_vertex_state *state)
430{
431   struct pipe_screen *screen = dd_screen(_screen)->screen;
432
433   screen->vertex_state_destroy(screen, state);
434}
435
436/********************************************************************
437 * memobj
438 */
439
440static struct pipe_memory_object *
441dd_screen_memobj_create_from_handle(struct pipe_screen *_screen,
442                                    struct winsys_handle *handle,
443                                    bool dedicated)
444{
445   struct pipe_screen *screen = dd_screen(_screen)->screen;
446
447   return screen->memobj_create_from_handle(screen, handle, dedicated);
448}
449
450static void
451dd_screen_memobj_destroy(struct pipe_screen *_screen,
452                         struct pipe_memory_object *memobj)
453{
454   struct pipe_screen *screen = dd_screen(_screen)->screen;
455
456   screen->memobj_destroy(screen, memobj);
457}
458/********************************************************************
459 * screen
460 */
461
462static char *
463dd_screen_finalize_nir(struct pipe_screen *_screen, void *nir)
464{
465   struct pipe_screen *screen = dd_screen(_screen)->screen;
466
467   return screen->finalize_nir(screen, nir);
468}
469
470static void
471dd_screen_destroy(struct pipe_screen *_screen)
472{
473   struct dd_screen *dscreen = dd_screen(_screen);
474   struct pipe_screen *screen = dscreen->screen;
475
476   screen->destroy(screen);
477   FREE(dscreen);
478}
479
480static void
481skip_space(const char **p)
482{
483   while (isspace(**p))
484      (*p)++;
485}
486
487static bool
488match_word(const char **cur, const char *word)
489{
490   size_t len = strlen(word);
491   if (strncmp(*cur, word, len) != 0)
492      return false;
493
494   const char *p = *cur + len;
495   if (*p) {
496      if (!isspace(*p))
497         return false;
498
499      *cur = p + 1;
500   } else {
501      *cur = p;
502   }
503
504   return true;
505}
506
507static bool
508match_uint(const char **cur, unsigned *value)
509{
510   char *end;
511   unsigned v = strtoul(*cur, &end, 0);
512   if (end == *cur || (*end && !isspace(*end)))
513      return false;
514   *cur = end;
515   *value = v;
516   return true;
517}
518
519struct pipe_screen *
520ddebug_screen_create(struct pipe_screen *screen)
521{
522   struct dd_screen *dscreen;
523   const char *option;
524   bool flush = false;
525   bool verbose = false;
526   bool transfers = false;
527   unsigned timeout = 1000;
528   unsigned apitrace_dump_call = 0;
529   enum dd_dump_mode mode = DD_DUMP_ONLY_HANGS;
530
531   option = debug_get_option("GALLIUM_DDEBUG", NULL);
532   if (!option)
533      return screen;
534
535   if (!strcmp(option, "help")) {
536      puts("Gallium driver debugger");
537      puts("");
538      puts("Usage:");
539      puts("");
540      puts("  GALLIUM_DDEBUG=\"[<timeout in ms>] [(always|apitrace <call#)] [flush] [transfers] [verbose]\"");
541      puts("  GALLIUM_DDEBUG_SKIP=[count]");
542      puts("");
543      puts("Dump context and driver information of draw calls into");
544      puts("$HOME/"DD_DIR"/. By default, watch for GPU hangs and only dump information");
545      puts("about draw calls related to the hang.");
546      puts("");
547      puts("<timeout in ms>");
548      puts("  Change the default timeout for GPU hang detection (default=1000ms).");
549      puts("  Setting this to 0 will disable GPU hang detection entirely.");
550      puts("");
551      puts("always");
552      puts("  Dump information about all draw calls.");
553      puts("");
554      puts("transfers");
555      puts("  Also dump and do hang detection on transfers.");
556      puts("");
557      puts("apitrace <call#>");
558      puts("  Dump information about the draw call corresponding to the given");
559      puts("  apitrace call number and exit.");
560      puts("");
561      puts("flush");
562      puts("  Flush after every draw call.");
563      puts("");
564      puts("verbose");
565      puts("  Write additional information to stderr.");
566      puts("");
567      puts("GALLIUM_DDEBUG_SKIP=count");
568      puts("  Skip dumping on the first count draw calls (only relevant with 'always').");
569      puts("");
570      exit(0);
571   }
572
573   for (;;) {
574      skip_space(&option);
575      if (!*option)
576         break;
577
578      if (match_word(&option, "always")) {
579         if (mode == DD_DUMP_APITRACE_CALL) {
580            printf("ddebug: both 'always' and 'apitrace' specified\n");
581            exit(1);
582         }
583
584         mode = DD_DUMP_ALL_CALLS;
585      } else if (match_word(&option, "flush")) {
586         flush = true;
587      } else if (match_word(&option, "transfers")) {
588         transfers = true;
589      } else if (match_word(&option, "verbose")) {
590         verbose = true;
591      } else if (match_word(&option, "apitrace")) {
592         if (mode != DD_DUMP_ONLY_HANGS) {
593            printf("ddebug: 'apitrace' can only appear once and not mixed with 'always'\n");
594            exit(1);
595         }
596
597         if (!match_uint(&option, &apitrace_dump_call)) {
598            printf("ddebug: expected call number after 'apitrace'\n");
599            exit(1);
600         }
601
602         mode = DD_DUMP_APITRACE_CALL;
603      } else if (match_uint(&option, &timeout)) {
604         /* no-op */
605      } else {
606         printf("ddebug: bad options: %s\n", option);
607         exit(1);
608      }
609   }
610
611   dscreen = CALLOC_STRUCT(dd_screen);
612   if (!dscreen)
613      return NULL;
614
615#define SCR_INIT(_member) \
616   dscreen->base._member = screen->_member ? dd_screen_##_member : NULL
617
618   dscreen->base.destroy = dd_screen_destroy;
619   dscreen->base.get_name = dd_screen_get_name;
620   dscreen->base.get_vendor = dd_screen_get_vendor;
621   dscreen->base.get_device_vendor = dd_screen_get_device_vendor;
622   SCR_INIT(get_disk_shader_cache);
623   dscreen->base.get_param = dd_screen_get_param;
624   dscreen->base.get_paramf = dd_screen_get_paramf;
625   dscreen->base.get_compute_param = dd_screen_get_compute_param;
626   dscreen->base.get_shader_param = dd_screen_get_shader_param;
627   dscreen->base.query_memory_info = dd_screen_query_memory_info;
628   /* get_video_param */
629   /* get_compute_param */
630   SCR_INIT(get_timestamp);
631   dscreen->base.context_create = dd_screen_context_create;
632   dscreen->base.is_format_supported = dd_screen_is_format_supported;
633   /* is_video_format_supported */
634   SCR_INIT(can_create_resource);
635   dscreen->base.resource_create = dd_screen_resource_create;
636   dscreen->base.resource_from_handle = dd_screen_resource_from_handle;
637   SCR_INIT(resource_from_memobj);
638   SCR_INIT(resource_from_user_memory);
639   SCR_INIT(check_resource_capability);
640   dscreen->base.resource_get_handle = dd_screen_resource_get_handle;
641   SCR_INIT(resource_get_param);
642   SCR_INIT(resource_get_info);
643   SCR_INIT(resource_changed);
644   dscreen->base.resource_destroy = dd_screen_resource_destroy;
645   SCR_INIT(flush_frontbuffer);
646   SCR_INIT(fence_reference);
647   SCR_INIT(fence_finish);
648   SCR_INIT(fence_get_fd);
649   SCR_INIT(memobj_create_from_handle);
650   SCR_INIT(memobj_destroy);
651   SCR_INIT(get_driver_query_info);
652   SCR_INIT(get_driver_query_group_info);
653   SCR_INIT(get_compiler_options);
654   SCR_INIT(get_driver_uuid);
655   SCR_INIT(get_device_uuid);
656   SCR_INIT(finalize_nir);
657   SCR_INIT(get_sparse_texture_virtual_page_size);
658   SCR_INIT(create_vertex_state);
659   SCR_INIT(vertex_state_destroy);
660
661#undef SCR_INIT
662
663   dscreen->screen = screen;
664   dscreen->timeout_ms = timeout;
665   dscreen->dump_mode = mode;
666   dscreen->flush_always = flush;
667   dscreen->transfers = transfers;
668   dscreen->verbose = verbose;
669   dscreen->apitrace_dump_call = apitrace_dump_call;
670
671   switch (dscreen->dump_mode) {
672   case DD_DUMP_ALL_CALLS:
673      fprintf(stderr, "Gallium debugger active. Logging all calls.\n");
674      break;
675   case DD_DUMP_APITRACE_CALL:
676      fprintf(stderr, "Gallium debugger active. Going to dump an apitrace call.\n");
677      break;
678   default:
679      fprintf(stderr, "Gallium debugger active.\n");
680      break;
681   }
682
683   if (dscreen->timeout_ms > 0)
684      fprintf(stderr, "Hang detection timeout is %ums.\n", dscreen->timeout_ms);
685   else
686      fprintf(stderr, "Hang detection is disabled.\n");
687
688   dscreen->skip_count = debug_get_num_option("GALLIUM_DDEBUG_SKIP", 0);
689   if (dscreen->skip_count > 0) {
690      fprintf(stderr, "Gallium debugger skipping the first %u draw calls.\n",
691              dscreen->skip_count);
692   }
693
694   return &dscreen->base;
695}
696