gallium/ddebug: add GALLIUM_DDEBUG_SKIP option
authorNicolai Hähnle <nicolai.haehnle@amd.com>
Tue, 8 Dec 2015 11:49:12 +0000 (06:49 -0500)
committerNicolai Hähnle <nicolai.haehnle@amd.com>
Sat, 12 Dec 2015 20:23:34 +0000 (15:23 -0500)
When we know that hangs occur only very late in a reproducible run (e.g.
apitrace), we can save a lot of debugging time by skipping the flush and hang
detection for earlier draw calls.

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
src/gallium/drivers/ddebug/dd_draw.c
src/gallium/drivers/ddebug/dd_pipe.h
src/gallium/drivers/ddebug/dd_screen.c

index b443c5b0b03e7c027a72f116ce0d5686bd88a039..0778099d4fdaed9ef1f44db4169008d087a02c1f 100644 (file)
@@ -588,8 +588,11 @@ dd_context_flush(struct pipe_context *_pipe,
 static void
 dd_before_draw(struct dd_context *dctx)
 {
-   if (dd_screen(dctx->base.screen)->mode == DD_DETECT_HANGS &&
-       !dd_screen(dctx->base.screen)->no_flush)
+   struct dd_screen *dscreen = dd_screen(dctx->base.screen);
+
+   if (dscreen->mode == DD_DETECT_HANGS &&
+       !dscreen->no_flush &&
+       dctx->num_draw_calls >= dscreen->skip_count)
       dd_flush_and_handle_hang(dctx, NULL, 0,
                                "GPU hang most likely caused by internal "
                                "driver commands");
@@ -598,22 +601,28 @@ dd_before_draw(struct dd_context *dctx)
 static void
 dd_after_draw(struct dd_context *dctx, struct dd_call *call)
 {
-   switch (dd_screen(dctx->base.screen)->mode) {
-   case DD_DETECT_HANGS:
-      if (!dd_screen(dctx->base.screen)->no_flush &&
-          dd_flush_and_check_hang(dctx, NULL, 0)) {
-         dd_dump_call(dctx, call, PIPE_DEBUG_DEVICE_IS_HUNG);
+   struct dd_screen *dscreen = dd_screen(dctx->base.screen);
 
-         /* Terminate the process to prevent future hangs. */
-         dd_kill_process();
+   if (dctx->num_draw_calls >= dscreen->skip_count) {
+      switch (dscreen->mode) {
+      case DD_DETECT_HANGS:
+         if (!dscreen->no_flush &&
+            dd_flush_and_check_hang(dctx, NULL, 0)) {
+            dd_dump_call(dctx, call, PIPE_DEBUG_DEVICE_IS_HUNG);
+
+            /* Terminate the process to prevent future hangs. */
+            dd_kill_process();
+         }
+         break;
+      case DD_DUMP_ALL_CALLS:
+         dd_dump_call(dctx, call, 0);
+         break;
+      default:
+         assert(0);
       }
-      break;
-   case DD_DUMP_ALL_CALLS:
-      dd_dump_call(dctx, call, 0);
-      break;
-   default:
-      assert(0);
    }
+
+   ++dctx->num_draw_calls;
 }
 
 static void
index 34f59203e4b2a43ecacdedff784b43588a2334d3..a045518dc16855b32086d37d988b072776138d8b 100644 (file)
@@ -45,6 +45,7 @@ struct dd_screen
    unsigned timeout_ms;
    enum dd_mode mode;
    bool no_flush;
+   unsigned skip_count;
 };
 
 struct dd_query
@@ -110,6 +111,8 @@ struct dd_context
    struct pipe_scissor_state scissors[PIPE_MAX_VIEWPORTS];
    struct pipe_viewport_state viewports[PIPE_MAX_VIEWPORTS];
    float tess_default_levels[6];
+
+   unsigned num_draw_calls;
 };
 
 
index a776580c9bb567c6e4ab7b8c273839c8da1134dd..2716845f58f72946894bc44abc37f7bd0c24cf28 100644 (file)
@@ -290,6 +290,9 @@ ddebug_screen_create(struct pipe_screen *screen)
       puts("    $HOME/"DD_DIR"/ when a hang is detected.");
       puts("    If 'noflush' is specified, only detect hangs in pipe->flush.");
       puts("");
+      puts("  GALLIUM_DDEBUG_SKIP=[count]");
+      puts("    Skip flush and hang detection for the given initial number of draw calls.");
+      puts("");
       exit(0);
    }
 
@@ -349,5 +352,11 @@ ddebug_screen_create(struct pipe_screen *screen)
       assert(0);
    }
 
+   dscreen->skip_count = debug_get_num_option("GALLIUM_DDEBUG_SKIP", 0);
+   if (dscreen->skip_count > 0) {
+      fprintf(stderr, "Gallium debugger skipping the first %u draw calls.\n",
+              dscreen->skip_count);
+   }
+
    return &dscreen->base;
 }