"Fossies" - the Fresh Open Source Software Archive

Member "mesa-20.1.8/src/gallium/auxiliary/driver_ddebug/dd_screen.c" (16 Sep 2020, 19845 Bytes) of package /linux/misc/mesa-20.1.8.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "dd_screen.c" see the Fossies "Dox" file reference documentation.

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