dd_draw.c 56.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
/**************************************************************************
 *
 * Copyright 2015 Advanced Micro Devices, Inc.
 * Copyright 2008 VMware, Inc.
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * on the rights to use, copy, modify, merge, publish, distribute, sub
 * license, and/or sell copies of the Software, and to permit persons to whom
 * the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 **************************************************************************/

#include "dd_pipe.h"

#include "util/u_dump.h"
31
#include "util/format/u_format.h"
32 33 34 35
#include "util/u_framebuffer.h"
#include "util/u_helpers.h"
#include "util/u_inlines.h"
#include "util/u_memory.h"
Nicolai Hähnle's avatar
Nicolai Hähnle committed
36
#include "util/u_process.h"
37
#include "tgsi/tgsi_parse.h"
38
#include "tgsi/tgsi_scan.h"
39
#include "util/os_time.h"
40
#include <inttypes.h>
41
#include "pipe/p_config.h"
42

43 44 45 46 47
void
dd_get_debug_filename_and_mkdir(char *buf, size_t buflen, bool verbose)
{
   static unsigned index;
   char proc_name[128], dir[256];
48

49 50 51 52 53
   if (!os_get_process_name(proc_name, sizeof(proc_name))) {
      fprintf(stderr, "dd: can't get the process name\n");
      strcpy(proc_name, "unknown");
   }

54
   snprintf(dir, sizeof(dir), "%s/"DD_DIR, debug_get_option("HOME", "."));
55 56 57 58

   if (mkdir(dir, 0774) && errno != EEXIST)
      fprintf(stderr, "dd: can't create a directory (%i)\n", errno);

59
   snprintf(buf, buflen, "%s/%s_%u_%08u", dir, proc_name, getpid(),
60
            (unsigned int)p_atomic_inc_return(&index) - 1);
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105

   if (verbose)
      fprintf(stderr, "dd: dumping to file %s\n", buf);
}

FILE *
dd_get_debug_file(bool verbose)
{
   char name[512];
   FILE *f;

   dd_get_debug_filename_and_mkdir(name, sizeof(name), verbose);
   f = fopen(name, "w");
   if (!f) {
      fprintf(stderr, "dd: can't open file %s\n", name);
      return NULL;
   }

   return f;
}

void
dd_parse_apitrace_marker(const char *string, int len, unsigned *call_number)
{
   unsigned num;
   char *s;

   if (len <= 0)
      return;

   /* Make it zero-terminated. */
   s = alloca(len + 1);
   memcpy(s, string, len);
   s[len] = 0;

   /* Parse the number. */
   errno = 0;
   num = strtol(s, NULL, 10);
   if (errno)
      return;

   *call_number = num;
}

void
106
dd_write_header(FILE *f, struct pipe_screen *screen, unsigned apitrace_call_number)
107
{
108 109 110
   char cmd_line[4096];
   if (os_get_command_line(cmd_line, sizeof(cmd_line)))
      fprintf(f, "Command: %s\n", cmd_line);
111 112 113
   fprintf(f, "Driver vendor: %s\n", screen->get_vendor(screen));
   fprintf(f, "Device vendor: %s\n", screen->get_device_vendor(screen));
   fprintf(f, "Device name: %s\n\n", screen->get_name(screen));
114

115
   if (apitrace_call_number)
116 117 118 119 120 121 122 123 124 125 126 127 128
      fprintf(f, "Last apitrace call: %u\n\n", apitrace_call_number);
}

FILE *
dd_get_file_stream(struct dd_screen *dscreen, unsigned apitrace_call_number)
{
   struct pipe_screen *screen = dscreen->screen;

   FILE *f = dd_get_debug_file(dscreen->verbose);
   if (!f)
      return NULL;

   dd_write_header(f, screen, apitrace_call_number);
129 130 131
   return f;
}

132 133 134
static void
dd_dump_dmesg(FILE *f)
{
135
#ifdef PIPE_OS_LINUX
136 137 138 139 140 141 142 143 144 145
   char line[2000];
   FILE *p = popen("dmesg | tail -n60", "r");

   if (!p)
      return;

   fprintf(f, "\nLast 60 lines of dmesg:\n\n");
   while (fgets(line, sizeof(line), p))
      fputs(line, f);

146
   pclose(p);
147
#endif
148 149
}

150
static unsigned
151
dd_num_active_viewports(struct dd_draw_state *dstate)
152 153 154 155
{
   struct tgsi_shader_info info;
   const struct tgsi_token *tokens;

156 157 158 159 160 161
   if (dstate->shaders[PIPE_SHADER_GEOMETRY])
      tokens = dstate->shaders[PIPE_SHADER_GEOMETRY]->state.shader.tokens;
   else if (dstate->shaders[PIPE_SHADER_TESS_EVAL])
      tokens = dstate->shaders[PIPE_SHADER_TESS_EVAL]->state.shader.tokens;
   else if (dstate->shaders[PIPE_SHADER_VERTEX])
      tokens = dstate->shaders[PIPE_SHADER_VERTEX]->state.shader.tokens;
162 163 164
   else
      return 1;

165 166 167 168 169 170 171
   if (tokens) {
      tgsi_scan_shader(tokens, &info);
      if (info.writes_viewport_index)
         return PIPE_MAX_VIEWPORTS;
   }

   return 1;
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
}

#define COLOR_RESET	"\033[0m"
#define COLOR_SHADER	"\033[1;32m"
#define COLOR_STATE	"\033[1;33m"

#define DUMP(name, var) do { \
   fprintf(f, COLOR_STATE #name ": " COLOR_RESET); \
   util_dump_##name(f, var); \
   fprintf(f, "\n"); \
} while(0)

#define DUMP_I(name, var, i) do { \
   fprintf(f, COLOR_STATE #name " %i: " COLOR_RESET, i); \
   util_dump_##name(f, var); \
   fprintf(f, "\n"); \
} while(0)

#define DUMP_M(name, var, member) do { \
   fprintf(f, "  " #member ": "); \
   util_dump_##name(f, (var)->member); \
   fprintf(f, "\n"); \
} while(0)

#define DUMP_M_ADDR(name, var, member) do { \
   fprintf(f, "  " #member ": "); \
   util_dump_##name(f, &(var)->member); \
   fprintf(f, "\n"); \
} while(0)

202 203 204 205 206 207
#define PRINT_NAMED(type, name, value) \
do { \
   fprintf(f, COLOR_STATE "%s" COLOR_RESET " = ", name); \
   util_dump_##type(f, value); \
   fprintf(f, "\n"); \
} while (0)
208 209 210 211 212 213 214

static void
util_dump_uint(FILE *f, unsigned i)
{
   fprintf(f, "%u", i);
}

215 216 217 218 219 220
static void
util_dump_int(FILE *f, int i)
{
   fprintf(f, "%d", i);
}

221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
static void
util_dump_hex(FILE *f, unsigned i)
{
   fprintf(f, "0x%x", i);
}

static void
util_dump_double(FILE *f, double d)
{
   fprintf(f, "%f", d);
}

static void
util_dump_format(FILE *f, enum pipe_format format)
{
   fprintf(f, "%s", util_format_name(format));
}

static void
util_dump_color_union(FILE *f, const union pipe_color_union *color)
{
   fprintf(f, "{f = {%f, %f, %f, %f}, ui = {%u, %u, %u, %u}",
           color->f[0], color->f[1], color->f[2], color->f[3],
           color->ui[0], color->ui[1], color->ui[2], color->ui[3]);
}

static void
248
dd_dump_render_condition(struct dd_draw_state *dstate, FILE *f)
249
{
250
   if (dstate->render_cond.query) {
251
      fprintf(f, "render condition:\n");
252
      DUMP_M(query_type, &dstate->render_cond, query->type);
253 254
      DUMP_M(uint, &dstate->render_cond, condition);
      DUMP_M(uint, &dstate->render_cond, mode);
255 256 257 258 259
      fprintf(f, "\n");
   }
}

static void
260
dd_dump_shader(struct dd_draw_state *dstate, enum pipe_shader_type sh, FILE *f)
261
{
262
   int i;
263 264 265 266 267 268 269 270 271
   const char *shader_str[PIPE_SHADER_TYPES];

   shader_str[PIPE_SHADER_VERTEX] = "VERTEX";
   shader_str[PIPE_SHADER_TESS_CTRL] = "TESS_CTRL";
   shader_str[PIPE_SHADER_TESS_EVAL] = "TESS_EVAL";
   shader_str[PIPE_SHADER_GEOMETRY] = "GEOMETRY";
   shader_str[PIPE_SHADER_FRAGMENT] = "FRAGMENT";
   shader_str[PIPE_SHADER_COMPUTE] = "COMPUTE";

272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
   if (sh == PIPE_SHADER_TESS_CTRL &&
       !dstate->shaders[PIPE_SHADER_TESS_CTRL] &&
       dstate->shaders[PIPE_SHADER_TESS_EVAL])
      fprintf(f, "tess_state: {default_outer_level = {%f, %f, %f, %f}, "
              "default_inner_level = {%f, %f}}\n",
              dstate->tess_default_levels[0],
              dstate->tess_default_levels[1],
              dstate->tess_default_levels[2],
              dstate->tess_default_levels[3],
              dstate->tess_default_levels[4],
              dstate->tess_default_levels[5]);

   if (sh == PIPE_SHADER_FRAGMENT)
      if (dstate->rs) {
         unsigned num_viewports = dd_num_active_viewports(dstate);

         if (dstate->rs->state.rs.clip_plane_enable)
            DUMP(clip_state, &dstate->clip_state);

         for (i = 0; i < num_viewports; i++)
            DUMP_I(viewport_state, &dstate->viewports[i], i);

         if (dstate->rs->state.rs.scissor)
            for (i = 0; i < num_viewports; i++)
               DUMP_I(scissor_state, &dstate->scissors[i], i);

         DUMP(rasterizer_state, &dstate->rs->state.rs);

         if (dstate->rs->state.rs.poly_stipple_enable)
            DUMP(poly_stipple, &dstate->polygon_stipple);
         fprintf(f, "\n");
      }

   if (!dstate->shaders[sh])
      return;

   fprintf(f, COLOR_SHADER "begin shader: %s" COLOR_RESET "\n", shader_str[sh]);
   DUMP(shader_state, &dstate->shaders[sh]->state.shader);

   for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++)
      if (dstate->constant_buffers[sh][i].buffer ||
            dstate->constant_buffers[sh][i].user_buffer) {
         DUMP_I(constant_buffer, &dstate->constant_buffers[sh][i], i);
         if (dstate->constant_buffers[sh][i].buffer)
            DUMP_M(resource, &dstate->constant_buffers[sh][i], buffer);
      }

   for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
      if (dstate->sampler_states[sh][i])
         DUMP_I(sampler_state, &dstate->sampler_states[sh][i]->state.sampler, i);

   for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
      if (dstate->sampler_views[sh][i]) {
         DUMP_I(sampler_view, dstate->sampler_views[sh][i], i);
         DUMP_M(resource, dstate->sampler_views[sh][i], texture);
      }

   for (i = 0; i < PIPE_MAX_SHADER_IMAGES; i++)
      if (dstate->shader_images[sh][i].resource) {
         DUMP_I(image_view, &dstate->shader_images[sh][i], i);
         if (dstate->shader_images[sh][i].resource)
            DUMP_M(resource, &dstate->shader_images[sh][i], resource);
      }

   for (i = 0; i < PIPE_MAX_SHADER_BUFFERS; i++)
      if (dstate->shader_buffers[sh][i].buffer) {
         DUMP_I(shader_buffer, &dstate->shader_buffers[sh][i], i);
         if (dstate->shader_buffers[sh][i].buffer)
            DUMP_M(resource, &dstate->shader_buffers[sh][i], buffer);
      }

   fprintf(f, COLOR_SHADER "end shader: %s" COLOR_RESET "\n\n", shader_str[sh]);
}

346 347 348 349 350 351 352
static void
dd_dump_flush(struct dd_draw_state *dstate, struct call_flush *info, FILE *f)
{
   fprintf(f, "%s:\n", __func__+8);
   DUMP_M(hex, info, flags);
}

353 354 355 356 357
static void
dd_dump_draw_vbo(struct dd_draw_state *dstate, struct pipe_draw_info *info, FILE *f)
{
   int sh, i;

358
   DUMP(draw_info, info);
359
   if (info->indirect) {
360 361
      if (info->indirect->buffer)
         DUMP_M(resource, info, indirect->buffer);
362 363
      if (info->indirect->indirect_draw_count)
         DUMP_M(resource, info, indirect->indirect_draw_count);
364 365 366
      if (info->indirect->count_from_stream_output)
         DUMP_M(stream_output_target, info,
                indirect->count_from_stream_output);
367 368
   }

369 370 371 372
   fprintf(f, "\n");

   /* TODO: dump active queries */

373
   dd_dump_render_condition(dstate, f);
374 375

   for (i = 0; i < PIPE_MAX_ATTRIBS; i++)
376
      if (dstate->vertex_buffers[i].buffer.resource) {
377
         DUMP_I(vertex_buffer, &dstate->vertex_buffers[i], i);
378 379
         if (!dstate->vertex_buffers[i].is_user_buffer)
            DUMP_M(resource, &dstate->vertex_buffers[i], buffer.resource);
380 381
      }

382
   if (dstate->velems) {
383
      PRINT_NAMED(uint, "num vertex elements",
384 385
                        dstate->velems->state.velems.count);
      for (i = 0; i < dstate->velems->state.velems.count; i++) {
386
         fprintf(f, "  ");
387
         DUMP_I(vertex_element, &dstate->velems->state.velems.velems[i], i);
388 389 390
      }
   }

391
   PRINT_NAMED(uint, "num stream output targets", dstate->num_so_targets);
392 393 394 395 396
   for (i = 0; i < dstate->num_so_targets; i++)
      if (dstate->so_targets[i]) {
         DUMP_I(stream_output_target, dstate->so_targets[i], i);
         DUMP_M(resource, dstate->so_targets[i], buffer);
         fprintf(f, "  offset = %i\n", dstate->so_offsets[i]);
397 398 399 400 401 402 403
      }

   fprintf(f, "\n");
   for (sh = 0; sh < PIPE_SHADER_TYPES; sh++) {
      if (sh == PIPE_SHADER_COMPUTE)
         continue;

404
      dd_dump_shader(dstate, sh, f);
405 406
   }

407 408 409
   if (dstate->dsa)
      DUMP(depth_stencil_alpha_state, &dstate->dsa->state.dsa);
   DUMP(stencil_ref, &dstate->stencil_ref);
410

411 412 413
   if (dstate->blend)
      DUMP(blend_state, &dstate->blend->state.blend);
   DUMP(blend_color, &dstate->blend_color);
414

415 416
   PRINT_NAMED(uint, "min_samples", dstate->min_samples);
   PRINT_NAMED(hex, "sample_mask", dstate->sample_mask);
417 418
   fprintf(f, "\n");

419 420 421
   DUMP(framebuffer_state, &dstate->framebuffer_state);
   for (i = 0; i < dstate->framebuffer_state.nr_cbufs; i++)
      if (dstate->framebuffer_state.cbufs[i]) {
422
         fprintf(f, "  " COLOR_STATE "cbufs[%i]:" COLOR_RESET "\n    ", i);
423
         DUMP(surface, dstate->framebuffer_state.cbufs[i]);
424
         fprintf(f, "    ");
425
         DUMP(resource, dstate->framebuffer_state.cbufs[i]->texture);
426
      }
427
   if (dstate->framebuffer_state.zsbuf) {
428
      fprintf(f, "  " COLOR_STATE "zsbuf:" COLOR_RESET "\n    ");
429
      DUMP(surface, dstate->framebuffer_state.zsbuf);
430
      fprintf(f, "    ");
431
      DUMP(resource, dstate->framebuffer_state.zsbuf->texture);
432 433 434 435
   }
   fprintf(f, "\n");
}

436
static void
437
dd_dump_launch_grid(struct dd_draw_state *dstate, struct pipe_grid_info *info, FILE *f)
438 439
{
   fprintf(f, "%s:\n", __func__+8);
440 441 442 443 444
   DUMP(grid_info, info);
   fprintf(f, "\n");

   dd_dump_shader(dstate, PIPE_SHADER_COMPUTE, f);
   fprintf(f, "\n");
445 446
}

447
static void
448
dd_dump_resource_copy_region(struct dd_draw_state *dstate,
449 450 451 452 453 454 455 456 457 458 459
                             struct call_resource_copy_region *info,
                             FILE *f)
{
   fprintf(f, "%s:\n", __func__+8);
   DUMP_M(resource, info, dst);
   DUMP_M(uint, info, dst_level);
   DUMP_M(uint, info, dstx);
   DUMP_M(uint, info, dsty);
   DUMP_M(uint, info, dstz);
   DUMP_M(resource, info, src);
   DUMP_M(uint, info, src_level);
460
   DUMP_M_ADDR(box, info, src_box);
461 462 463
}

static void
464
dd_dump_blit(struct dd_draw_state *dstate, struct pipe_blit_info *info, FILE *f)
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
{
   fprintf(f, "%s:\n", __func__+8);
   DUMP_M(resource, info, dst.resource);
   DUMP_M(uint, info, dst.level);
   DUMP_M_ADDR(box, info, dst.box);
   DUMP_M(format, info, dst.format);

   DUMP_M(resource, info, src.resource);
   DUMP_M(uint, info, src.level);
   DUMP_M_ADDR(box, info, src.box);
   DUMP_M(format, info, src.format);

   DUMP_M(hex, info, mask);
   DUMP_M(uint, info, filter);
   DUMP_M(uint, info, scissor_enable);
   DUMP_M_ADDR(scissor_state, info, scissor);
   DUMP_M(uint, info, render_condition_enable);

   if (info->render_condition_enable)
484
      dd_dump_render_condition(dstate, f);
485 486
}

487
static void
488
dd_dump_generate_mipmap(struct dd_draw_state *dstate, FILE *f)
489 490 491 492 493
{
   fprintf(f, "%s:\n", __func__+8);
   /* TODO */
}

494 495 496 497 498 499 500 501 502 503 504 505
static void
dd_dump_get_query_result_resource(struct call_get_query_result_resource *info, FILE *f)
{
   fprintf(f, "%s:\n", __func__ + 8);
   DUMP_M(query_type, info, query_type);
   DUMP_M(uint, info, wait);
   DUMP_M(query_value_type, info, result_type);
   DUMP_M(int, info, index);
   DUMP_M(resource, info, resource);
   DUMP_M(uint, info, offset);
}

506
static void
507
dd_dump_flush_resource(struct dd_draw_state *dstate, struct pipe_resource *res,
508 509 510 511 512 513 514
                       FILE *f)
{
   fprintf(f, "%s:\n", __func__+8);
   DUMP(resource, res);
}

static void
515
dd_dump_clear(struct dd_draw_state *dstate, struct call_clear *info, FILE *f)
516 517 518
{
   fprintf(f, "%s:\n", __func__+8);
   DUMP_M(uint, info, buffers);
519 520 521
   fprintf(f, "  scissor_state: %d,%d %d,%d\n",
              info->scissor_state.minx, info->scissor_state.miny,
              info->scissor_state.maxx, info->scissor_state.maxy);
522
   DUMP_M_ADDR(color_union, info, color);
523 524 525 526 527
   DUMP_M(double, info, depth);
   DUMP_M(hex, info, stencil);
}

static void
528
dd_dump_clear_buffer(struct dd_draw_state *dstate, struct call_clear_buffer *info,
529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545
                     FILE *f)
{
   int i;
   const char *value = (const char*)info->clear_value;

   fprintf(f, "%s:\n", __func__+8);
   DUMP_M(resource, info, res);
   DUMP_M(uint, info, offset);
   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");
}

546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
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);
}

596 597 598 599 600 601 602
static void
dd_dump_clear_texture(struct dd_draw_state *dstate, FILE *f)
{
   fprintf(f, "%s:\n", __func__+8);
   /* TODO */
}

603
static void
604
dd_dump_clear_render_target(struct dd_draw_state *dstate, FILE *f)
605 606 607 608 609 610
{
   fprintf(f, "%s:\n", __func__+8);
   /* TODO */
}

static void
611
dd_dump_clear_depth_stencil(struct dd_draw_state *dstate, FILE *f)
612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628
{
   fprintf(f, "%s:\n", __func__+8);
   /* TODO */
}

static void
dd_dump_driver_state(struct dd_context *dctx, FILE *f, unsigned flags)
{
   if (dctx->pipe->dump_debug_state) {
	   fprintf(f,"\n\n**************************************************"
		     "***************************\n");
	   fprintf(f, "Driver-specific state:\n\n");
	   dctx->pipe->dump_debug_state(dctx->pipe, f, flags);
   }
}

static void
629
dd_dump_call(FILE *f, struct dd_draw_state *state, struct dd_call *call)
630 631
{
   switch (call->type) {
632 633 634
   case CALL_FLUSH:
      dd_dump_flush(state, &call->info.flush, f);
      break;
635
   case CALL_DRAW_VBO:
636
      dd_dump_draw_vbo(state, &call->info.draw_vbo.draw, f);
637
      break;
638
   case CALL_LAUNCH_GRID:
639
      dd_dump_launch_grid(state, &call->info.launch_grid, f);
640
      break;
641
   case CALL_RESOURCE_COPY_REGION:
642
      dd_dump_resource_copy_region(state,
643
                                   &call->info.resource_copy_region, f);
644 645
      break;
   case CALL_BLIT:
646
      dd_dump_blit(state, &call->info.blit, f);
647 648
      break;
   case CALL_FLUSH_RESOURCE:
649
      dd_dump_flush_resource(state, call->info.flush_resource, f);
650 651
      break;
   case CALL_CLEAR:
652
      dd_dump_clear(state, &call->info.clear, f);
653 654
      break;
   case CALL_CLEAR_BUFFER:
655
      dd_dump_clear_buffer(state, &call->info.clear_buffer, f);
656
      break;
657 658 659
   case CALL_CLEAR_TEXTURE:
      dd_dump_clear_texture(state, f);
      break;
660
   case CALL_CLEAR_RENDER_TARGET:
661
      dd_dump_clear_render_target(state, f);
662 663
      break;
   case CALL_CLEAR_DEPTH_STENCIL:
664
      dd_dump_clear_depth_stencil(state, f);
665 666
      break;
   case CALL_GENERATE_MIPMAP:
667
      dd_dump_generate_mipmap(state, f);
668
      break;
669 670 671
   case CALL_GET_QUERY_RESULT_RESOURCE:
      dd_dump_get_query_result_resource(&call->info.get_query_result_resource, f);
      break;
672 673 674 675 676 677 678 679 680 681 682 683 684 685 686
   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;
687
   }
688 689
}

690 691 692
static void
dd_kill_process(void)
{
693
#ifdef PIPE_OS_UNIX
694
   sync();
695
#endif
696 697 698
   fprintf(stderr, "dd: Aborting the process...\n");
   fflush(stdout);
   fflush(stderr);
Marek Olšák's avatar
Marek Olšák committed
699
   exit(1);
700 701
}

702 703 704 705
static void
dd_unreference_copy_of_call(struct dd_call *dst)
{
   switch (dst->type) {
706 707
   case CALL_FLUSH:
      break;
708
   case CALL_DRAW_VBO:
709
      pipe_so_target_reference(&dst->info.draw_vbo.indirect.count_from_stream_output, NULL);
710 711
      pipe_resource_reference(&dst->info.draw_vbo.indirect.buffer, NULL);
      pipe_resource_reference(&dst->info.draw_vbo.indirect.indirect_draw_count, NULL);
712 713 714 715 716
      if (dst->info.draw_vbo.draw.index_size &&
          !dst->info.draw_vbo.draw.has_user_indices)
         pipe_resource_reference(&dst->info.draw_vbo.draw.index.resource, NULL);
      else
         dst->info.draw_vbo.draw.index.user = NULL;
717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736
      break;
   case CALL_LAUNCH_GRID:
      pipe_resource_reference(&dst->info.launch_grid.indirect, NULL);
      break;
   case CALL_RESOURCE_COPY_REGION:
      pipe_resource_reference(&dst->info.resource_copy_region.dst, NULL);
      pipe_resource_reference(&dst->info.resource_copy_region.src, NULL);
      break;
   case CALL_BLIT:
      pipe_resource_reference(&dst->info.blit.dst.resource, NULL);
      pipe_resource_reference(&dst->info.blit.src.resource, NULL);
      break;
   case CALL_FLUSH_RESOURCE:
      pipe_resource_reference(&dst->info.flush_resource, NULL);
      break;
   case CALL_CLEAR:
      break;
   case CALL_CLEAR_BUFFER:
      pipe_resource_reference(&dst->info.clear_buffer.res, NULL);
      break;
737 738
   case CALL_CLEAR_TEXTURE:
      break;
739 740 741 742 743 744 745
   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;
746 747 748
   case CALL_GET_QUERY_RESULT_RESOURCE:
      pipe_resource_reference(&dst->info.get_query_result_resource.resource, NULL);
      break;
749 750 751 752 753 754 755 756 757 758 759 760 761 762 763
   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;
764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812
   }
}

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.
    */
   memset(state->base.vertex_buffers, 0,
          sizeof(state->base.vertex_buffers));
   memset(state->base.so_targets, 0,
          sizeof(state->base.so_targets));
   memset(state->base.constant_buffers, 0,
          sizeof(state->base.constant_buffers));
   memset(state->base.sampler_views, 0,
          sizeof(state->base.sampler_views));
   memset(state->base.shader_images, 0,
          sizeof(state->base.shader_images));
   memset(state->base.shader_buffers, 0,
          sizeof(state->base.shader_buffers));
   memset(&state->base.framebuffer_state, 0,
          sizeof(state->base.framebuffer_state));

   memset(state->shaders, 0, sizeof(state->shaders));

   state->base.render_cond.query = &state->render_cond;

   for (i = 0; i < PIPE_SHADER_TYPES; i++) {
      state->base.shaders[i] = &state->shaders[i];
      for (j = 0; j < PIPE_MAX_SAMPLERS; j++)
         state->base.sampler_states[i][j] = &state->sampler_states[i][j];
   }

   state->base.velems = &state->velems;
   state->base.rs = &state->rs;
   state->base.dsa = &state->dsa;
   state->base.blend = &state->blend;
}

static void
dd_unreference_copy_of_draw_state(struct dd_draw_state_copy *state)
{
   struct dd_draw_state *dst = &state->base;
   unsigned i,j;

   for (i = 0; i < ARRAY_SIZE(dst->vertex_buffers); i++)
813
      pipe_vertex_buffer_unreference(&dst->vertex_buffers[i]);
814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847
   for (i = 0; i < ARRAY_SIZE(dst->so_targets); i++)
      pipe_so_target_reference(&dst->so_targets[i], NULL);

   for (i = 0; i < PIPE_SHADER_TYPES; i++) {
      if (dst->shaders[i])
         tgsi_free_tokens(dst->shaders[i]->state.shader.tokens);

      for (j = 0; j < PIPE_MAX_CONSTANT_BUFFERS; j++)
         pipe_resource_reference(&dst->constant_buffers[i][j].buffer, NULL);
      for (j = 0; j < PIPE_MAX_SAMPLERS; j++)
         pipe_sampler_view_reference(&dst->sampler_views[i][j], NULL);
      for (j = 0; j < PIPE_MAX_SHADER_IMAGES; j++)
         pipe_resource_reference(&dst->shader_images[i][j].resource, NULL);
      for (j = 0; j < PIPE_MAX_SHADER_BUFFERS; j++)
         pipe_resource_reference(&dst->shader_buffers[i][j].buffer, NULL);
   }

   util_unreference_framebuffer_state(&dst->framebuffer_state);
}

static void
dd_copy_draw_state(struct dd_draw_state *dst, struct dd_draw_state *src)
{
   unsigned i,j;

   if (src->render_cond.query) {
      *dst->render_cond.query = *src->render_cond.query;
      dst->render_cond.condition = src->render_cond.condition;
      dst->render_cond.mode = src->render_cond.mode;
   } else {
      dst->render_cond.query = NULL;
   }

   for (i = 0; i < ARRAY_SIZE(src->vertex_buffers); i++) {
848 849
      pipe_vertex_buffer_reference(&dst->vertex_buffers[i],
                                   &src->vertex_buffers[i]);
850 851 852
   }

   dst->num_so_targets = src->num_so_targets;
853
   for (i = 0; i < src->num_so_targets; i++)
854 855 856 857 858 859 860 861 862 863 864
      pipe_so_target_reference(&dst->so_targets[i], src->so_targets[i]);
   memcpy(dst->so_offsets, src->so_offsets, sizeof(src->so_offsets));

   for (i = 0; i < PIPE_SHADER_TYPES; i++) {
      if (!src->shaders[i]) {
         dst->shaders[i] = NULL;
         continue;
      }

      if (src->shaders[i]) {
         dst->shaders[i]->state.shader = src->shaders[i]->state.shader;
865 866 867 868 869 870
         if (src->shaders[i]->state.shader.tokens) {
            dst->shaders[i]->state.shader.tokens =
               tgsi_dup_tokens(src->shaders[i]->state.shader.tokens);
         } else {
            dst->shaders[i]->state.shader.ir.nir = NULL;
         }
871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890
      } else {
         dst->shaders[i] = NULL;
      }

      for (j = 0; j < PIPE_MAX_CONSTANT_BUFFERS; j++) {
         pipe_resource_reference(&dst->constant_buffers[i][j].buffer,
                                 src->constant_buffers[i][j].buffer);
         memcpy(&dst->constant_buffers[i][j], &src->constant_buffers[i][j],
                sizeof(src->constant_buffers[i][j]));
      }

      for (j = 0; j < PIPE_MAX_SAMPLERS; j++) {
         pipe_sampler_view_reference(&dst->sampler_views[i][j],
                                     src->sampler_views[i][j]);
         if (src->sampler_states[i][j])
            dst->sampler_states[i][j]->state.sampler =
               src->sampler_states[i][j]->state.sampler;
         else
            dst->sampler_states[i][j] = NULL;
      }
891 892 893 894 895 896 897 898 899 900 901 902 903 904

      for (j = 0; j < PIPE_MAX_SHADER_IMAGES; j++) {
         pipe_resource_reference(&dst->shader_images[i][j].resource,
                                 src->shader_images[i][j].resource);
         memcpy(&dst->shader_images[i][j], &src->shader_images[i][j],
                sizeof(src->shader_images[i][j]));
      }

      for (j = 0; j < PIPE_MAX_SHADER_BUFFERS; j++) {
         pipe_resource_reference(&dst->shader_buffers[i][j].buffer,
                                 src->shader_buffers[i][j].buffer);
         memcpy(&dst->shader_buffers[i][j], &src->shader_buffers[i][j],
                sizeof(src->shader_buffers[i][j]));
      }
905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940
   }

   if (src->velems)
      dst->velems->state.velems = src->velems->state.velems;
   else
      dst->velems = NULL;

   if (src->rs)
      dst->rs->state.rs = src->rs->state.rs;
   else
      dst->rs = NULL;

   if (src->dsa)
      dst->dsa->state.dsa = src->dsa->state.dsa;
   else
      dst->dsa = NULL;

   if (src->blend)
      dst->blend->state.blend = src->blend->state.blend;
   else
      dst->blend = NULL;

   dst->blend_color = src->blend_color;
   dst->stencil_ref = src->stencil_ref;
   dst->sample_mask = src->sample_mask;
   dst->min_samples = src->min_samples;
   dst->clip_state = src->clip_state;
   util_copy_framebuffer_state(&dst->framebuffer_state, &src->framebuffer_state);
   memcpy(dst->scissors, src->scissors, sizeof(src->scissors));
   memcpy(dst->viewports, src->viewports, sizeof(src->viewports));
   memcpy(dst->tess_default_levels, src->tess_default_levels,
          sizeof(src->tess_default_levels));
   dst->apitrace_call_number = src->apitrace_call_number;
}

static void
941 942 943 944 945 946 947 948 949 950 951 952 953 954
dd_free_record(struct pipe_screen *screen, struct dd_draw_record *record)
{
   u_log_page_destroy(record->log_page);
   dd_unreference_copy_of_call(&record->call);
   dd_unreference_copy_of_draw_state(&record->draw_state);
   screen->fence_reference(screen, &record->prev_bottom_of_pipe, NULL);
   screen->fence_reference(screen, &record->top_of_pipe, NULL);
   screen->fence_reference(screen, &record->bottom_of_pipe, NULL);
   util_queue_fence_destroy(&record->driver_finished);
   FREE(record);
}

static void
dd_write_record(FILE *f, struct dd_draw_record *record)
955
{
956 957 958 959 960
   PRINT_NAMED(ptr, "pipe", record->dctx->pipe);
   PRINT_NAMED(ns, "time before (API call)", record->time_before);
   PRINT_NAMED(ns, "time after (driver done)", record->time_after);
   fprintf(f, "\n");

961
   dd_dump_call(f, &record->draw_state.base, &record->call);
962

963 964 965 966 967 968
   if (record->log_page) {
      fprintf(f,"\n\n**************************************************"
                "***************************\n");
      fprintf(f, "Context Log:\n\n");
      u_log_page_print(record->log_page, f);
   }
969 970 971
}

static void
972
dd_maybe_dump_record(struct dd_screen *dscreen, struct dd_draw_record *record)
973
{
974 975 976
   if (dscreen->dump_mode == DD_DUMP_ONLY_HANGS ||
       (dscreen->dump_mode == DD_DUMP_APITRACE_CALL &&
        dscreen->apitrace_dump_call != record->draw_state.base.apitrace_call_number))
977 978
      return;

979 980 981 982 983 984 985
   char name[512];
   dd_get_debug_filename_and_mkdir(name, sizeof(name), dscreen->verbose);
   FILE *f = fopen(name, "w");
   if (!f) {
      fprintf(stderr, "dd: failed to open %s\n", name);
      return;
   }
986

987 988
   dd_write_header(f, dscreen->screen, record->draw_state.base.apitrace_call_number);
   dd_write_record(f, record);
989

990 991 992
   fclose(f);
}

993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009
static const char *
dd_fence_state(struct pipe_screen *screen, struct pipe_fence_handle *fence,
               bool *not_reached)
{
   if (!fence)
      return "---";

   bool ok = screen->fence_finish(screen, NULL, fence, 0);

   if (not_reached && !ok)
      *not_reached = true;

   return ok ? "YES" : "NO ";
}

static void
dd_report_hang(struct dd_context *dctx)
1010 1011
{
   struct dd_screen *dscreen = dd_screen(dctx->base.screen);
1012 1013 1014 1015
   struct pipe_screen *screen = dscreen->screen;
   bool encountered_hang = false;
   bool stop_output = false;
   unsigned num_later = 0;
1016

1017
   fprintf(stderr, "GPU hang detected, collecting information...\n\n");
1018

1019 1020
   fprintf(stderr, "Draw #   driver  prev BOP  TOP  BOP  dump file\n"
                   "-------------------------------------------------------------\n");
1021

1022 1023 1024 1025 1026 1027
   list_for_each_entry(struct dd_draw_record, record, &dctx->records, list) {
      if (!encountered_hang &&
          screen->fence_finish(screen, NULL, record->bottom_of_pipe, 0)) {
         dd_maybe_dump_record(dscreen, record);
         continue;
      }
1028

1029 1030 1031 1032 1033
      if (stop_output) {
         dd_maybe_dump_record(dscreen, record);
         num_later++;
         continue;
      }
1034

1035 1036 1037 1038 1039
      bool driver = util_queue_fence_is_signalled(&record->driver_finished);
      bool top_not_reached = false;
      const char *prev_bop = dd_fence_state(screen, record->prev_bottom_of_pipe, NULL);
      const char *top = dd_fence_state(screen, record->top_of_pipe, &top_not_reached);
      const char *bop = dd_fence_state(screen, record->bottom_of_pipe, NULL);
1040

1041 1042
      fprintf(stderr, "%-9u %s      %s     %s  %s  ",
              record->draw_call, driver ? "YES" : "NO ", prev_bop, top, bop);
1043

1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056
      char name[512];
      dd_get_debug_filename_and_mkdir(name, sizeof(name), false);

      FILE *f = fopen(name, "w");
      if (!f) {
         fprintf(stderr, "fopen failed\n");
      } else {
         fprintf(stderr, "%s\n", name);

         dd_write_header(f, dscreen->screen, record->draw_state.base.apitrace_call_number);
         dd_write_record(f, record);

         fclose(f);
1057 1058
      }

1059 1060 1061
      if (top_not_reached)
         stop_output = true;
      encountered_hang = true;
1062 1063
   }

1064 1065
   if (num_later)
      fprintf(stderr, "... and %u additional draws.\n", num_later);
1066

1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078
   char name[512];
   dd_get_debug_filename_and_mkdir(name, sizeof(name), false);
   FILE *f = fopen(name, "w");
   if (!f) {
      fprintf(stderr, "fopen failed\n");
   } else {
      dd_write_header(f, dscreen->screen, 0);
      dd_dump_driver_state(dctx, f, PIPE_DUMP_DEVICE_STATUS_REGISTERS);
      dd_dump_dmesg(f);
      fclose(f);
   }

1079 1080 1081
   fprintf(stderr, "\nDone.\n");
   dd_kill_process();
}
1082

1083 1084 1085 1086 1087 1088 1089
int
dd_thread_main(void *input)
{
   struct dd_context *dctx = (struct dd_context *)input;
   struct dd_screen *dscreen = dd_screen(dctx->base.screen);
   struct pipe_screen *screen = dscreen->screen;

Nicolai Hähnle's avatar
Nicolai Hähnle committed
1090 1091 1092
   const char *process_name = util_get_process_name();
   if (process_name) {
      char threadname[16];
1093 1094 1095
      snprintf(threadname, sizeof(threadname), "%.*s:ddbg",
               (int)MIN2(strlen(process_name), sizeof(threadname) - 6),
               process_name);
Nicolai Hähnle's avatar
Nicolai Hähnle committed
1096 1097 1098
      u_thread_setname(threadname);
   }

1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109
   mtx_lock(&dctx->mutex);

   for (;;) {
      struct list_head records;
      list_replace(&dctx->records, &records);
      list_inithead(&dctx->records);
      dctx->num_records = 0;

      if (dctx->api_stalled)
         cnd_signal(&dctx->cond);

1110
      if (list_is_empty(&records)) {
1111 1112 1113
         if (dctx->kill_thread)
            break;

1114 1115 1116
         cnd_wait(&dctx->cond, &dctx->mutex);
         continue;
      }
1117

1118 1119
      mtx_unlock(&dctx->mutex);

1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139
      /* Wait for the youngest draw. This means hangs can take a bit longer
       * to detect, but it's more efficient this way.  */
      struct dd_draw_record *youngest =
         list_last_entry(&records, struct dd_draw_record, list);

      if (dscreen->timeout_ms > 0) {
         uint64_t abs_timeout = os_time_get_absolute_timeout(
                                 (uint64_t)dscreen->timeout_ms * 1000*1000);

         if (!util_queue_fence_wait_timeout(&youngest->driver_finished, abs_timeout) ||
             !screen->fence_finish(screen, NULL, youngest->bottom_of_pipe,
                                   (uint64_t)dscreen->timeout_ms * 1000*1000)) {
            mtx_lock(&dctx->mutex);
            list_splice(&records, &dctx->records);
            dd_report_hang(dctx);
            /* we won't actually get here */
            mtx_unlock(&dctx->mutex);
         }
      } else {
         util_queue_fence_wait(&youngest->driver_finished);
1140 1141 1142 1143 1144 1145 1146 1147 1148 1149
      }

      list_for_each_entry_safe(struct dd_draw_record, record, &records, list) {
         dd_maybe_dump_record(dscreen, record);
         list_del(&record->list);
         dd_free_record(screen, record);
      }

      mtx_lock(&dctx->mutex);
   }
1150
   mtx_unlock(&dctx->mutex);
1151 1152 1153
   return 0;
}

1154 1155
static struct dd_draw_record *
dd_create_record(struct dd_context *dctx)
1156 1157 1158 1159 1160
{
   struct dd_draw_record *record;

   record = MALLOC_STRUCT(dd_draw_record);
   if (!record)
1161
      return NULL;
1162

1163 1164
   record->dctx = dctx;
   record->draw_call = dctx->num_draw_calls;
1165

1166 1167 1168 1169 1170
   record->prev_bottom_of_pipe = NULL;
   record->top_of_pipe = NULL;
   record->bottom_of_pipe = NULL;
   record->log_page = NULL;
   util_queue_fence_init(&record->driver_finished);
1171
   util_queue_fence_reset(&record->driver_finished);
1172 1173 1174 1175

   dd_init_copy_of_draw_state(&record->draw_state);
   dd_copy_draw_state(&record->draw_state.base, &dctx->draw_state);

1176
   return record;
1177 1178
}