[Mesa-dev] [PATCH v2 24/26] ddebug: optionally handle transfer commands like draws

Nicolai Hähnle nhaehnle at gmail.com
Mon Nov 6 10:23:55 UTC 2017


From: Nicolai Hähnle <nicolai.haehnle at amd.com>

Transfer commands can have associated GPU operations.

Enabled by passing GALLIUM_DDEBUG=transfers.

Reviewed-by: Marek Olšák <marek.olsak at amd.com>
---
 src/gallium/drivers/ddebug/dd_context.c |  65 ---------
 src/gallium/drivers/ddebug/dd_draw.c    | 234 ++++++++++++++++++++++++++++++++
 src/gallium/drivers/ddebug/dd_pipe.h    |  46 +++++++
 src/gallium/drivers/ddebug/dd_screen.c  |   9 +-
 4 files changed, 288 insertions(+), 66 deletions(-)

diff --git a/src/gallium/drivers/ddebug/dd_context.c b/src/gallium/drivers/ddebug/dd_context.c
index 558708df58d..dd7b3e086cd 100644
--- a/src/gallium/drivers/ddebug/dd_context.c
+++ b/src/gallium/drivers/ddebug/dd_context.c
@@ -601,80 +601,20 @@ dd_context_destroy(struct pipe_context *_pipe)
       }
    }
    u_log_context_destroy(&dctx->log);
 
    pipe->destroy(pipe);
    FREE(dctx);
 }
 
 
 /********************************************************************
- * transfer
- */
-
-static void *
-dd_context_transfer_map(struct pipe_context *_pipe,
-                        struct pipe_resource *resource, unsigned level,
-                        unsigned usage, const struct pipe_box *box,
-                        struct pipe_transfer **transfer)
-{
-   struct pipe_context *pipe = dd_context(_pipe)->pipe;
-
-   return pipe->transfer_map(pipe, resource, level, usage, box, transfer);
-}
-
-static void
-dd_context_transfer_flush_region(struct pipe_context *_pipe,
-                                 struct pipe_transfer *transfer,
-                                 const struct pipe_box *box)
-{
-   struct pipe_context *pipe = dd_context(_pipe)->pipe;
-
-   pipe->transfer_flush_region(pipe, transfer, box);
-}
-
-static void
-dd_context_transfer_unmap(struct pipe_context *_pipe,
-                          struct pipe_transfer *transfer)
-{
-   struct pipe_context *pipe = dd_context(_pipe)->pipe;
-
-   pipe->transfer_unmap(pipe, transfer);
-}
-
-static void
-dd_context_buffer_subdata(struct pipe_context *_pipe,
-                          struct pipe_resource *resource,
-                          unsigned usage, unsigned offset,
-                          unsigned size, const void *data)
-{
-   struct pipe_context *pipe = dd_context(_pipe)->pipe;
-
-   pipe->buffer_subdata(pipe, resource, usage, offset, size, data);
-}
-
-static void
-dd_context_texture_subdata(struct pipe_context *_pipe,
-                           struct pipe_resource *resource,
-                           unsigned level, unsigned usage,
-                           const struct pipe_box *box,
-                           const void *data, unsigned stride,
-                           unsigned layer_stride)
-{
-   struct pipe_context *pipe = dd_context(_pipe)->pipe;
-
-   pipe->texture_subdata(pipe, resource, level, usage, box, data,
-                         stride, layer_stride);
-}
-
-
-/********************************************************************
  * miscellaneous
  */
 
 static void
 dd_context_texture_barrier(struct pipe_context *_pipe, unsigned flags)
 {
    struct pipe_context *pipe = dd_context(_pipe)->pipe;
 
    pipe->texture_barrier(pipe, flags);
 }
@@ -884,25 +824,20 @@ dd_context_create(struct dd_screen *dscreen, struct pipe_context *pipe)
    CTX_INIT(set_shader_buffers);
    CTX_INIT(set_shader_images);
    CTX_INIT(set_vertex_buffers);
    CTX_INIT(create_stream_output_target);
    CTX_INIT(stream_output_target_destroy);
    CTX_INIT(set_stream_output_targets);
    CTX_INIT(create_sampler_view);
    CTX_INIT(sampler_view_destroy);
    CTX_INIT(create_surface);
    CTX_INIT(surface_destroy);
-   CTX_INIT(transfer_map);
-   CTX_INIT(transfer_flush_region);
-   CTX_INIT(transfer_unmap);
-   CTX_INIT(buffer_subdata);
-   CTX_INIT(texture_subdata);
    CTX_INIT(texture_barrier);
    CTX_INIT(memory_barrier);
    CTX_INIT(resource_commit);
    /* create_video_codec */
    /* create_video_buffer */
    /* set_compute_resources */
    /* set_global_binding */
    CTX_INIT(get_sample_position);
    CTX_INIT(invalidate_resource);
    CTX_INIT(get_device_reset_status);
diff --git a/src/gallium/drivers/ddebug/dd_draw.c b/src/gallium/drivers/ddebug/dd_draw.c
index 182d6f297a1..a25017114d8 100644
--- a/src/gallium/drivers/ddebug/dd_draw.c
+++ b/src/gallium/drivers/ddebug/dd_draw.c
@@ -461,20 +461,70 @@ dd_dump_clear_buffer(struct dd_draw_state *dstate, struct call_clear_buffer *inf
    DUMP_M(uint, info, size);
    DUMP_M(uint, info, clear_value_size);
 
    fprintf(f, "  clear_value:");
    for (i = 0; i < info->clear_value_size; i++)
       fprintf(f, " %02x", value[i]);
    fprintf(f, "\n");
 }
 
 static void
+dd_dump_transfer_map(struct call_transfer_map *info, FILE *f)
+{
+   fprintf(f, "%s:\n", __func__+8);
+   DUMP_M_ADDR(transfer, info, transfer);
+   DUMP_M(ptr, info, transfer_ptr);
+   DUMP_M(ptr, info, ptr);
+}
+
+static void
+dd_dump_transfer_flush_region(struct call_transfer_flush_region *info, FILE *f)
+{
+   fprintf(f, "%s:\n", __func__+8);
+   DUMP_M_ADDR(transfer, info, transfer);
+   DUMP_M(ptr, info, transfer_ptr);
+   DUMP_M_ADDR(box, info, box);
+}
+
+static void
+dd_dump_transfer_unmap(struct call_transfer_unmap *info, FILE *f)
+{
+   fprintf(f, "%s:\n", __func__+8);
+   DUMP_M_ADDR(transfer, info, transfer);
+   DUMP_M(ptr, info, transfer_ptr);
+}
+
+static void
+dd_dump_buffer_subdata(struct call_buffer_subdata *info, FILE *f)
+{
+   fprintf(f, "%s:\n", __func__+8);
+   DUMP_M(resource, info, resource);
+   DUMP_M(transfer_usage, info, usage);
+   DUMP_M(uint, info, offset);
+   DUMP_M(uint, info, size);
+   DUMP_M(ptr, info, data);
+}
+
+static void
+dd_dump_texture_subdata(struct call_texture_subdata *info, FILE *f)
+{
+   fprintf(f, "%s:\n", __func__+8);
+   DUMP_M(resource, info, resource);
+   DUMP_M(uint, info, level);
+   DUMP_M(transfer_usage, info, usage);
+   DUMP_M_ADDR(box, info, box);
+   DUMP_M(ptr, info, data);
+   DUMP_M(uint, info, stride);
+   DUMP_M(uint, info, layer_stride);
+}
+
+static void
 dd_dump_clear_texture(struct dd_draw_state *dstate, FILE *f)
 {
    fprintf(f, "%s:\n", __func__+8);
    /* TODO */
 }
 
 static void
 dd_dump_clear_render_target(struct dd_draw_state *dstate, FILE *f)
 {
    fprintf(f, "%s:\n", __func__+8);
@@ -533,20 +583,35 @@ dd_dump_call(FILE *f, struct dd_draw_state *state, struct dd_call *call)
       break;
    case CALL_CLEAR_DEPTH_STENCIL:
       dd_dump_clear_depth_stencil(state, f);
       break;
    case CALL_GENERATE_MIPMAP:
       dd_dump_generate_mipmap(state, f);
       break;
    case CALL_GET_QUERY_RESULT_RESOURCE:
       dd_dump_get_query_result_resource(&call->info.get_query_result_resource, f);
       break;
+   case CALL_TRANSFER_MAP:
+      dd_dump_transfer_map(&call->info.transfer_map, f);
+      break;
+   case CALL_TRANSFER_FLUSH_REGION:
+      dd_dump_transfer_flush_region(&call->info.transfer_flush_region, f);
+      break;
+   case CALL_TRANSFER_UNMAP:
+      dd_dump_transfer_unmap(&call->info.transfer_unmap, f);
+      break;
+   case CALL_BUFFER_SUBDATA:
+      dd_dump_buffer_subdata(&call->info.buffer_subdata, f);
+      break;
+   case CALL_TEXTURE_SUBDATA:
+      dd_dump_texture_subdata(&call->info.texture_subdata, f);
+      break;
    }
 }
 
 static void
 dd_kill_process(void)
 {
    sync();
    fprintf(stderr, "dd: Aborting the process...\n");
    fflush(stdout);
    fflush(stderr);
@@ -591,20 +656,35 @@ dd_unreference_copy_of_call(struct dd_call *dst)
    case CALL_CLEAR_RENDER_TARGET:
       break;
    case CALL_CLEAR_DEPTH_STENCIL:
       break;
    case CALL_GENERATE_MIPMAP:
       pipe_resource_reference(&dst->info.generate_mipmap.res, NULL);
       break;
    case CALL_GET_QUERY_RESULT_RESOURCE:
       pipe_resource_reference(&dst->info.get_query_result_resource.resource, NULL);
       break;
+   case CALL_TRANSFER_MAP:
+      pipe_resource_reference(&dst->info.transfer_map.transfer.resource, NULL);
+      break;
+   case CALL_TRANSFER_FLUSH_REGION:
+      pipe_resource_reference(&dst->info.transfer_flush_region.transfer.resource, NULL);
+      break;
+   case CALL_TRANSFER_UNMAP:
+      pipe_resource_reference(&dst->info.transfer_unmap.transfer.resource, NULL);
+      break;
+   case CALL_BUFFER_SUBDATA:
+      pipe_resource_reference(&dst->info.buffer_subdata.resource, NULL);
+      break;
+   case CALL_TEXTURE_SUBDATA:
+      pipe_resource_reference(&dst->info.texture_subdata.resource, NULL);
+      break;
    }
 }
 
 static void
 dd_init_copy_of_draw_state(struct dd_draw_state_copy *state)
 {
    unsigned i,j;
 
    /* Just clear pointers to gallium objects. Don't clear the whole structure,
     * because it would kill performance with its size of 130 KB.
@@ -1385,27 +1465,181 @@ dd_context_clear_texture(struct pipe_context *_pipe,
    struct pipe_context *pipe = dctx->pipe;
    struct dd_draw_record *record = dd_create_record(dctx);
 
    record->call.type = CALL_CLEAR_TEXTURE;
 
    dd_before_draw(dctx, record);
    pipe->clear_texture(pipe, res, level, box, data);
    dd_after_draw(dctx, record);
 }
 
+/********************************************************************
+ * transfer
+ */
+
+static void *
+dd_context_transfer_map(struct pipe_context *_pipe,
+                        struct pipe_resource *resource, unsigned level,
+                        unsigned usage, const struct pipe_box *box,
+                        struct pipe_transfer **transfer)
+{
+   struct dd_context *dctx = dd_context(_pipe);
+   struct pipe_context *pipe = dctx->pipe;
+   struct dd_draw_record *record =
+      dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL;
+
+   if (record) {
+      record->call.type = CALL_TRANSFER_MAP;
+
+      dd_before_draw(dctx, record);
+   }
+   void *ptr = pipe->transfer_map(pipe, resource, level, usage, box, transfer);
+   if (record) {
+      record->call.info.transfer_map.transfer_ptr = *transfer;
+      record->call.info.transfer_map.ptr = ptr;
+      if (*transfer) {
+         record->call.info.transfer_map.transfer = **transfer;
+         record->call.info.transfer_map.transfer.resource = NULL;
+         pipe_resource_reference(&record->call.info.transfer_map.transfer.resource,
+                                 (*transfer)->resource);
+      } else {
+         memset(&record->call.info.transfer_map.transfer, 0, sizeof(struct pipe_transfer));
+      }
+
+      dd_after_draw(dctx, record);
+   }
+   return ptr;
+}
+
+static void
+dd_context_transfer_flush_region(struct pipe_context *_pipe,
+                                 struct pipe_transfer *transfer,
+                                 const struct pipe_box *box)
+{
+   struct dd_context *dctx = dd_context(_pipe);
+   struct pipe_context *pipe = dctx->pipe;
+   struct dd_draw_record *record =
+      dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL;
+
+   if (record) {
+      record->call.type = CALL_TRANSFER_FLUSH_REGION;
+      record->call.info.transfer_flush_region.transfer_ptr = transfer;
+      record->call.info.transfer_flush_region.box = *box;
+      record->call.info.transfer_flush_region.transfer = *transfer;
+      record->call.info.transfer_flush_region.transfer.resource = NULL;
+      pipe_resource_reference(
+            &record->call.info.transfer_flush_region.transfer.resource,
+            transfer->resource);
+
+      dd_before_draw(dctx, record);
+   }
+   pipe->transfer_flush_region(pipe, transfer, box);
+   if (record)
+      dd_after_draw(dctx, record);
+}
+
+static void
+dd_context_transfer_unmap(struct pipe_context *_pipe,
+                          struct pipe_transfer *transfer)
+{
+   struct dd_context *dctx = dd_context(_pipe);
+   struct pipe_context *pipe = dctx->pipe;
+   struct dd_draw_record *record =
+      dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL;
+
+   if (record) {
+      record->call.type = CALL_TRANSFER_UNMAP;
+      record->call.info.transfer_unmap.transfer_ptr = transfer;
+      record->call.info.transfer_unmap.transfer = *transfer;
+      record->call.info.transfer_unmap.transfer.resource = NULL;
+      pipe_resource_reference(
+            &record->call.info.transfer_unmap.transfer.resource,
+            transfer->resource);
+
+      dd_before_draw(dctx, record);
+   }
+   pipe->transfer_unmap(pipe, transfer);
+   if (record)
+      dd_after_draw(dctx, record);
+}
+
+static void
+dd_context_buffer_subdata(struct pipe_context *_pipe,
+                          struct pipe_resource *resource,
+                          unsigned usage, unsigned offset,
+                          unsigned size, const void *data)
+{
+   struct dd_context *dctx = dd_context(_pipe);
+   struct pipe_context *pipe = dctx->pipe;
+   struct dd_draw_record *record =
+      dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL;
+
+   if (record) {
+      record->call.type = CALL_BUFFER_SUBDATA;
+      record->call.info.buffer_subdata.resource = NULL;
+      pipe_resource_reference(&record->call.info.buffer_subdata.resource, resource);
+      record->call.info.buffer_subdata.usage = usage;
+      record->call.info.buffer_subdata.offset = offset;
+      record->call.info.buffer_subdata.size = size;
+      record->call.info.buffer_subdata.data = data;
+
+      dd_before_draw(dctx, record);
+   }
+   pipe->buffer_subdata(pipe, resource, usage, offset, size, data);
+   if (record)
+      dd_after_draw(dctx, record);
+}
+
+static void
+dd_context_texture_subdata(struct pipe_context *_pipe,
+                           struct pipe_resource *resource,
+                           unsigned level, unsigned usage,
+                           const struct pipe_box *box,
+                           const void *data, unsigned stride,
+                           unsigned layer_stride)
+{
+   struct dd_context *dctx = dd_context(_pipe);
+   struct pipe_context *pipe = dctx->pipe;
+   struct dd_draw_record *record =
+      dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL;
+
+   if (record) {
+      record->call.type = CALL_TEXTURE_SUBDATA;
+      record->call.info.texture_subdata.resource = NULL;
+      pipe_resource_reference(&record->call.info.texture_subdata.resource, resource);
+      record->call.info.texture_subdata.level = level;
+      record->call.info.texture_subdata.usage = usage;
+      record->call.info.texture_subdata.box = *box;
+      record->call.info.texture_subdata.data = data;
+      record->call.info.texture_subdata.stride = stride;
+      record->call.info.texture_subdata.layer_stride = layer_stride;
+
+      dd_before_draw(dctx, record);
+   }
+   pipe->texture_subdata(pipe, resource, level, usage, box, data,
+                         stride, layer_stride);
+   if (record)
+      dd_after_draw(dctx, record);
+}
+
 void
 dd_init_draw_functions(struct dd_context *dctx)
 {
    CTX_INIT(flush);
    CTX_INIT(draw_vbo);
    CTX_INIT(launch_grid);
    CTX_INIT(resource_copy_region);
    CTX_INIT(blit);
    CTX_INIT(clear);
    CTX_INIT(clear_render_target);
    CTX_INIT(clear_depth_stencil);
    CTX_INIT(clear_buffer);
    CTX_INIT(clear_texture);
    CTX_INIT(flush_resource);
    CTX_INIT(generate_mipmap);
    CTX_INIT(get_query_result_resource);
+   CTX_INIT(transfer_map);
+   CTX_INIT(transfer_flush_region);
+   CTX_INIT(transfer_unmap);
+   CTX_INIT(buffer_subdata);
+   CTX_INIT(texture_subdata);
 }
diff --git a/src/gallium/drivers/ddebug/dd_pipe.h b/src/gallium/drivers/ddebug/dd_pipe.h
index 607ebbb2b96..07c4d55017f 100644
--- a/src/gallium/drivers/ddebug/dd_pipe.h
+++ b/src/gallium/drivers/ddebug/dd_pipe.h
@@ -45,39 +45,45 @@ enum dd_dump_mode {
    DD_DUMP_APITRACE_CALL,
 };
 
 struct dd_screen
 {
    struct pipe_screen base;
    struct pipe_screen *screen;
    unsigned timeout_ms;
    enum dd_dump_mode dump_mode;
    bool flush_always;
+   bool transfers;
    bool verbose;
    unsigned skip_count;
    unsigned apitrace_dump_call;
 };
 
 enum call_type
 {
    CALL_DRAW_VBO,
    CALL_LAUNCH_GRID,
    CALL_RESOURCE_COPY_REGION,
    CALL_BLIT,
    CALL_FLUSH_RESOURCE,
    CALL_CLEAR,
    CALL_CLEAR_BUFFER,
    CALL_CLEAR_TEXTURE,
    CALL_CLEAR_RENDER_TARGET,
    CALL_CLEAR_DEPTH_STENCIL,
    CALL_GENERATE_MIPMAP,
    CALL_GET_QUERY_RESULT_RESOURCE,
+   CALL_TRANSFER_MAP,
+   CALL_TRANSFER_FLUSH_REGION,
+   CALL_TRANSFER_UNMAP,
+   CALL_BUFFER_SUBDATA,
+   CALL_TEXTURE_SUBDATA,
 };
 
 struct call_resource_copy_region
 {
    struct pipe_resource *dst;
    unsigned dst_level;
    unsigned dstx, dsty, dstz;
    struct pipe_resource *src;
    unsigned src_level;
    struct pipe_box src_box;
@@ -117,34 +123,74 @@ struct call_draw_info {
 struct call_get_query_result_resource {
    struct pipe_query *query;
    enum pipe_query_type query_type;
    boolean wait;
    enum pipe_query_value_type result_type;
    int index;
    struct pipe_resource *resource;
    unsigned offset;
 };
 
+struct call_transfer_map {
+   struct pipe_transfer *transfer_ptr;
+   struct pipe_transfer transfer;
+   void *ptr;
+};
+
+struct call_transfer_flush_region {
+   struct pipe_transfer *transfer_ptr;
+   struct pipe_transfer transfer;
+   struct pipe_box box;
+};
+
+struct call_transfer_unmap {
+   struct pipe_transfer *transfer_ptr;
+   struct pipe_transfer transfer;
+};
+
+struct call_buffer_subdata {
+   struct pipe_resource *resource;
+   unsigned usage;
+   unsigned offset;
+   unsigned size;
+   const void *data;
+};
+
+struct call_texture_subdata {
+   struct pipe_resource *resource;
+   unsigned level;
+   unsigned usage;
+   struct pipe_box box;
+   const void *data;
+   unsigned stride;
+   unsigned layer_stride;
+};
+
 struct dd_call
 {
    enum call_type type;
 
    union {
       struct call_draw_info draw_vbo;
       struct pipe_grid_info launch_grid;
       struct call_resource_copy_region resource_copy_region;
       struct pipe_blit_info blit;
       struct pipe_resource *flush_resource;
       struct call_clear clear;
       struct call_clear_buffer clear_buffer;
       struct call_generate_mipmap generate_mipmap;
       struct call_get_query_result_resource get_query_result_resource;
+      struct call_transfer_map transfer_map;
+      struct call_transfer_flush_region transfer_flush_region;
+      struct call_transfer_unmap transfer_unmap;
+      struct call_buffer_subdata buffer_subdata;
+      struct call_texture_subdata texture_subdata;
    } info;
 };
 
 struct dd_query
 {
    unsigned type;
    struct pipe_query *query;
 };
 
 struct dd_state
diff --git a/src/gallium/drivers/ddebug/dd_screen.c b/src/gallium/drivers/ddebug/dd_screen.c
index 11d1d8c1e9c..5b2be28a969 100644
--- a/src/gallium/drivers/ddebug/dd_screen.c
+++ b/src/gallium/drivers/ddebug/dd_screen.c
@@ -421,47 +421,51 @@ match_uint(const char **cur, unsigned *value)
    return true;
 }
 
 struct pipe_screen *
 ddebug_screen_create(struct pipe_screen *screen)
 {
    struct dd_screen *dscreen;
    const char *option;
    bool flush = false;
    bool verbose = false;
+   bool transfers = false;
    unsigned timeout = 1000;
    unsigned apitrace_dump_call = 0;
    enum dd_dump_mode mode = DD_DUMP_ONLY_HANGS;
 
    option = debug_get_option("GALLIUM_DDEBUG", NULL);
    if (!option)
       return screen;
 
    if (!strcmp(option, "help")) {
       puts("Gallium driver debugger");
       puts("");
       puts("Usage:");
       puts("");
-      puts("  GALLIUM_DDEBUG=\"[<timeout in ms>] [(always|apitrace <call#)] [flush] [verbose]\"");
+      puts("  GALLIUM_DDEBUG=\"[<timeout in ms>] [(always|apitrace <call#)] [flush] [transfers] [verbose]\"");
       puts("  GALLIUM_DDEBUG_SKIP=[count]");
       puts("");
       puts("Dump context and driver information of draw calls into");
       puts("$HOME/"DD_DIR"/. By default, watch for GPU hangs and only dump information");
       puts("about draw calls related to the hang.");
       puts("");
       puts("<timeout in ms>");
       puts("  Change the default timeout for GPU hang detection (default=1000ms).");
       puts("  Setting this to 0 will disable GPU hang detection entirely.");
       puts("");
       puts("always");
       puts("  Dump information about all draw calls.");
       puts("");
+      puts("transfers");
+      puts("  Also dump and do hang detection on transfers.");
+      puts("");
       puts("apitrace <call#>");
       puts("  Dump information about the draw call corresponding to the given");
       puts("  apitrace call number and exit.");
       puts("");
       puts("flush");
       puts("  Flush after every draw call.");
       puts("");
       puts("verbose");
       puts("  Write additional information to stderr.");
       puts("");
@@ -478,20 +482,22 @@ ddebug_screen_create(struct pipe_screen *screen)
 
       if (match_word(&option, "always")) {
          if (mode == DD_DUMP_APITRACE_CALL) {
             printf("ddebug: both 'always' and 'apitrace' specified\n");
             exit(1);
          }
 
          mode = DD_DUMP_ALL_CALLS;
       } else if (match_word(&option, "flush")) {
          flush = true;
+      } else if (match_word(&option, "transfers")) {
+         transfers = true;
       } else if (match_word(&option, "verbose")) {
          verbose = true;
       } else if (match_word(&option, "apitrace")) {
          if (mode != DD_DUMP_ONLY_HANGS) {
             printf("ddebug: 'apitrace' can only appear once and not mixed with 'always'\n");
             exit(1);
          }
 
          if (!match_uint(&option, &apitrace_dump_call)) {
             printf("ddebug: expected call number after 'apitrace'\n");
@@ -549,20 +555,21 @@ ddebug_screen_create(struct pipe_screen *screen)
    SCR_INIT(get_compiler_options);
    SCR_INIT(get_driver_uuid);
    SCR_INIT(get_device_uuid);
 
 #undef SCR_INIT
 
    dscreen->screen = screen;
    dscreen->timeout_ms = timeout;
    dscreen->dump_mode = mode;
    dscreen->flush_always = flush;
+   dscreen->transfers = transfers;
    dscreen->verbose = verbose;
    dscreen->apitrace_dump_call = apitrace_dump_call;
 
    switch (dscreen->dump_mode) {
    case DD_DUMP_ALL_CALLS:
       fprintf(stderr, "Gallium debugger active. Logging all calls.\n");
       break;
    case DD_DUMP_APITRACE_CALL:
       fprintf(stderr, "Gallium debugger active. Going to dump an apitrace call.\n");
       break;
-- 
2.11.0



More information about the mesa-dev mailing list