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 30#include "util/u_dump.h" 31#include "util/format/u_format.h" 32#include "util/u_framebuffer.h" 33#include "util/u_helpers.h" 34#include "util/u_inlines.h" 35#include "util/u_memory.h" 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 43void 44dd_get_debug_filename_and_mkdir(char *buf, size_t buflen, bool verbose) 45{ 46 static unsigned index; 47 char proc_name[128], dir[256]; 48 49 if (!os_get_process_name(proc_name, sizeof(proc_name))) { 50 fprintf(stderr, "dd: can't get the process name\n"); 51 strcpy(proc_name, "unknown"); 52 } 53 54 snprintf(dir, sizeof(dir), "%s/"DD_DIR, debug_get_option("HOME", ".")); 55 56 if (mkdir(dir, 0774) && errno != EEXIST) 57 fprintf(stderr, "dd: can't create a directory (%i)\n", errno); 58 59 snprintf(buf, buflen, "%s/%s_%u_%08u", dir, proc_name, (unsigned int)getpid(), 60 (unsigned int)p_atomic_inc_return(&index) - 1); 61 62 if (verbose) 63 fprintf(stderr, "dd: dumping to file %s\n", buf); 64} 65 66FILE * 67dd_get_debug_file(bool verbose) 68{ 69 char name[512]; 70 FILE *f; 71 72 dd_get_debug_filename_and_mkdir(name, sizeof(name), verbose); 73 f = fopen(name, "w"); 74 if (!f) { 75 fprintf(stderr, "dd: can't open file %s\n", name); 76 return NULL; 77 } 78 79 return f; 80} 81 82void 83dd_parse_apitrace_marker(const char *string, int len, unsigned *call_number) 84{ 85 unsigned num; 86 char *s; 87 88 if (len <= 0) 89 return; 90 91 /* Make it zero-terminated. */ 92 s = alloca(len + 1); 93 memcpy(s, string, len); 94 s[len] = 0; 95 96 /* Parse the number. */ 97 errno = 0; 98 num = strtol(s, NULL, 10); 99 if (errno) 100 return; 101 102 *call_number = num; 103} 104 105void 106dd_write_header(FILE *f, struct pipe_screen *screen, unsigned apitrace_call_number) 107{ 108 char cmd_line[4096]; 109 if (os_get_command_line(cmd_line, sizeof(cmd_line))) 110 fprintf(f, "Command: %s\n", cmd_line); 111 fprintf(f, "Driver vendor: %s\n", screen->get_vendor(screen)); 112 fprintf(f, "Device vendor: %s\n", screen->get_device_vendor(screen)); 113 fprintf(f, "Device name: %s\n\n", screen->get_name(screen)); 114 115 if (apitrace_call_number) 116 fprintf(f, "Last apitrace call: %u\n\n", apitrace_call_number); 117} 118 119FILE * 120dd_get_file_stream(struct dd_screen *dscreen, unsigned apitrace_call_number) 121{ 122 struct pipe_screen *screen = dscreen->screen; 123 124 FILE *f = dd_get_debug_file(dscreen->verbose); 125 if (!f) 126 return NULL; 127 128 dd_write_header(f, screen, apitrace_call_number); 129 return f; 130} 131 132static void 133dd_dump_dmesg(FILE *f) 134{ 135#ifdef PIPE_OS_LINUX 136 char line[2000]; 137 FILE *p = popen("dmesg | tail -n60", "r"); 138 139 if (!p) 140 return; 141 142 fprintf(f, "\nLast 60 lines of dmesg:\n\n"); 143 while (fgets(line, sizeof(line), p)) 144 fputs(line, f); 145 146 pclose(p); 147#endif 148} 149 150static unsigned 151dd_num_active_viewports(struct dd_draw_state *dstate) 152{ 153 struct tgsi_shader_info info; 154 const struct tgsi_token *tokens; 155 156 if (dstate->shaders[PIPE_SHADER_GEOMETRY]) 157 tokens = dstate->shaders[PIPE_SHADER_GEOMETRY]->state.shader.tokens; 158 else if (dstate->shaders[PIPE_SHADER_TESS_EVAL]) 159 tokens = dstate->shaders[PIPE_SHADER_TESS_EVAL]->state.shader.tokens; 160 else if (dstate->shaders[PIPE_SHADER_VERTEX]) 161 tokens = dstate->shaders[PIPE_SHADER_VERTEX]->state.shader.tokens; 162 else 163 return 1; 164 165 if (tokens) { 166 tgsi_scan_shader(tokens, &info); 167 if (info.writes_viewport_index) 168 return PIPE_MAX_VIEWPORTS; 169 } 170 171 return 1; 172} 173 174#define COLOR_RESET "\033[0m" 175#define COLOR_SHADER "\033[1;32m" 176#define COLOR_STATE "\033[1;33m" 177 178#define DUMP(name, var) do { \ 179 fprintf(f, COLOR_STATE #name ": " COLOR_RESET); \ 180 util_dump_##name(f, var); \ 181 fprintf(f, "\n"); \ 182} while(0) 183 184#define DUMP_I(name, var, i) do { \ 185 fprintf(f, COLOR_STATE #name " %i: " COLOR_RESET, i); \ 186 util_dump_##name(f, var); \ 187 fprintf(f, "\n"); \ 188} while(0) 189 190#define DUMP_M(name, var, member) do { \ 191 fprintf(f, " " #member ": "); \ 192 util_dump_##name(f, (var)->member); \ 193 fprintf(f, "\n"); \ 194} while(0) 195 196#define DUMP_M_ADDR(name, var, member) do { \ 197 fprintf(f, " " #member ": "); \ 198 util_dump_##name(f, &(var)->member); \ 199 fprintf(f, "\n"); \ 200} while(0) 201 202#define PRINT_NAMED(type, name, value) \ 203do { \ 204 fprintf(f, COLOR_STATE "%s" COLOR_RESET " = ", name); \ 205 util_dump_##type(f, value); \ 206 fprintf(f, "\n"); \ 207} while (0) 208 209static void 210util_dump_uint(FILE *f, unsigned i) 211{ 212 fprintf(f, "%u", i); 213} 214 215static void 216util_dump_int(FILE *f, int i) 217{ 218 fprintf(f, "%d", i); 219} 220 221static void 222util_dump_hex(FILE *f, unsigned i) 223{ 224 fprintf(f, "0x%x", i); 225} 226 227static void 228util_dump_double(FILE *f, double d) 229{ 230 fprintf(f, "%f", d); 231} 232 233static void 234util_dump_format(FILE *f, enum pipe_format format) 235{ 236 fprintf(f, "%s", util_format_name(format)); 237} 238 239static void 240util_dump_color_union(FILE *f, const union pipe_color_union *color) 241{ 242 fprintf(f, "{f = {%f, %f, %f, %f}, ui = {%u, %u, %u, %u}", 243 color->f[0], color->f[1], color->f[2], color->f[3], 244 color->ui[0], color->ui[1], color->ui[2], color->ui[3]); 245} 246 247static void 248dd_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 DUMP_M(uint, &dstate->render_cond, condition); 254 DUMP_M(uint, &dstate->render_cond, mode); 255 fprintf(f, "\n"); 256 } 257} 258 259static void 260dd_dump_shader(struct dd_draw_state *dstate, enum pipe_shader_type sh, FILE *f) 261{ 262 int i; 263 const char *shader_str[PIPE_SHADER_TYPES]; 264 265 shader_str[PIPE_SHADER_VERTEX] = "VERTEX"; 266 shader_str[PIPE_SHADER_TESS_CTRL] = "TESS_CTRL"; 267 shader_str[PIPE_SHADER_TESS_EVAL] = "TESS_EVAL"; 268 shader_str[PIPE_SHADER_GEOMETRY] = "GEOMETRY"; 269 shader_str[PIPE_SHADER_FRAGMENT] = "FRAGMENT"; 270 shader_str[PIPE_SHADER_COMPUTE] = "COMPUTE"; 271 272 if (sh == PIPE_SHADER_TESS_CTRL && 273 !dstate->shaders[PIPE_SHADER_TESS_CTRL] && 274 dstate->shaders[PIPE_SHADER_TESS_EVAL]) 275 fprintf(f, "tess_state: {default_outer_level = {%f, %f, %f, %f}, " 276 "default_inner_level = {%f, %f}}\n", 277 dstate->tess_default_levels[0], 278 dstate->tess_default_levels[1], 279 dstate->tess_default_levels[2], 280 dstate->tess_default_levels[3], 281 dstate->tess_default_levels[4], 282 dstate->tess_default_levels[5]); 283 284 if (sh == PIPE_SHADER_FRAGMENT) 285 if (dstate->rs) { 286 unsigned num_viewports = dd_num_active_viewports(dstate); 287 288 if (dstate->rs->state.rs.clip_plane_enable) 289 DUMP(clip_state, &dstate->clip_state); 290 291 for (i = 0; i < num_viewports; i++) 292 DUMP_I(viewport_state, &dstate->viewports[i], i); 293 294 if (dstate->rs->state.rs.scissor) 295 for (i = 0; i < num_viewports; i++) 296 DUMP_I(scissor_state, &dstate->scissors[i], i); 297 298 DUMP(rasterizer_state, &dstate->rs->state.rs); 299 300 if (dstate->rs->state.rs.poly_stipple_enable) 301 DUMP(poly_stipple, &dstate->polygon_stipple); 302 fprintf(f, "\n"); 303 } 304 305 if (!dstate->shaders[sh]) 306 return; 307 308 fprintf(f, COLOR_SHADER "begin shader: %s" COLOR_RESET "\n", shader_str[sh]); 309 DUMP(shader_state, &dstate->shaders[sh]->state.shader); 310 311 for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) 312 if (dstate->constant_buffers[sh][i].buffer || 313 dstate->constant_buffers[sh][i].user_buffer) { 314 DUMP_I(constant_buffer, &dstate->constant_buffers[sh][i], i); 315 if (dstate->constant_buffers[sh][i].buffer) 316 DUMP_M(resource, &dstate->constant_buffers[sh][i], buffer); 317 } 318 319 for (i = 0; i < PIPE_MAX_SAMPLERS; i++) 320 if (dstate->sampler_states[sh][i]) 321 DUMP_I(sampler_state, &dstate->sampler_states[sh][i]->state.sampler, i); 322 323 for (i = 0; i < PIPE_MAX_SAMPLERS; i++) 324 if (dstate->sampler_views[sh][i]) { 325 DUMP_I(sampler_view, dstate->sampler_views[sh][i], i); 326 DUMP_M(resource, dstate->sampler_views[sh][i], texture); 327 } 328 329 for (i = 0; i < PIPE_MAX_SHADER_IMAGES; i++) 330 if (dstate->shader_images[sh][i].resource) { 331 DUMP_I(image_view, &dstate->shader_images[sh][i], i); 332 if (dstate->shader_images[sh][i].resource) 333 DUMP_M(resource, &dstate->shader_images[sh][i], resource); 334 } 335 336 for (i = 0; i < PIPE_MAX_SHADER_BUFFERS; i++) 337 if (dstate->shader_buffers[sh][i].buffer) { 338 DUMP_I(shader_buffer, &dstate->shader_buffers[sh][i], i); 339 if (dstate->shader_buffers[sh][i].buffer) 340 DUMP_M(resource, &dstate->shader_buffers[sh][i], buffer); 341 } 342 343 fprintf(f, COLOR_SHADER "end shader: %s" COLOR_RESET "\n\n", shader_str[sh]); 344} 345 346static void 347dd_dump_flush(struct dd_draw_state *dstate, struct call_flush *info, FILE *f) 348{ 349 fprintf(f, "%s:\n", __func__+8); 350 DUMP_M(hex, info, flags); 351} 352 353static void 354dd_dump_draw_vbo(struct dd_draw_state *dstate, struct pipe_draw_info *info, 355 unsigned drawid_offset, 356 const struct pipe_draw_indirect_info *indirect, 357 const struct pipe_draw_start_count_bias *draw, FILE *f) 358{ 359 int sh, i; 360 361 DUMP(draw_info, info); 362 PRINT_NAMED(int, "drawid offset", drawid_offset); 363 DUMP(draw_start_count_bias, draw); 364 if (indirect) { 365 if (indirect->buffer) 366 DUMP_M(resource, indirect, buffer); 367 if (indirect->indirect_draw_count) 368 DUMP_M(resource, indirect, indirect_draw_count); 369 if (indirect->count_from_stream_output) 370 DUMP_M(stream_output_target, indirect, count_from_stream_output); 371 } 372 373 fprintf(f, "\n"); 374 375 /* TODO: dump active queries */ 376 377 dd_dump_render_condition(dstate, f); 378 379 for (i = 0; i < PIPE_MAX_ATTRIBS; i++) 380 if (dstate->vertex_buffers[i].buffer.resource) { 381 DUMP_I(vertex_buffer, &dstate->vertex_buffers[i], i); 382 if (!dstate->vertex_buffers[i].is_user_buffer) 383 DUMP_M(resource, &dstate->vertex_buffers[i], buffer.resource); 384 } 385 386 if (dstate->velems) { 387 PRINT_NAMED(uint, "num vertex elements", 388 dstate->velems->state.velems.count); 389 for (i = 0; i < dstate->velems->state.velems.count; i++) { 390 fprintf(f, " "); 391 DUMP_I(vertex_element, &dstate->velems->state.velems.velems[i], i); 392 } 393 } 394 395 PRINT_NAMED(uint, "num stream output targets", dstate->num_so_targets); 396 for (i = 0; i < dstate->num_so_targets; i++) 397 if (dstate->so_targets[i]) { 398 DUMP_I(stream_output_target, dstate->so_targets[i], i); 399 DUMP_M(resource, dstate->so_targets[i], buffer); 400 fprintf(f, " offset = %i\n", dstate->so_offsets[i]); 401 } 402 403 fprintf(f, "\n"); 404 for (sh = 0; sh < PIPE_SHADER_TYPES; sh++) { 405 if (sh == PIPE_SHADER_COMPUTE) 406 continue; 407 408 dd_dump_shader(dstate, sh, f); 409 } 410 411 if (dstate->dsa) 412 DUMP(depth_stencil_alpha_state, &dstate->dsa->state.dsa); 413 DUMP(stencil_ref, &dstate->stencil_ref); 414 415 if (dstate->blend) 416 DUMP(blend_state, &dstate->blend->state.blend); 417 DUMP(blend_color, &dstate->blend_color); 418 419 PRINT_NAMED(uint, "min_samples", dstate->min_samples); 420 PRINT_NAMED(hex, "sample_mask", dstate->sample_mask); 421 fprintf(f, "\n"); 422 423 DUMP(framebuffer_state, &dstate->framebuffer_state); 424 for (i = 0; i < dstate->framebuffer_state.nr_cbufs; i++) 425 if (dstate->framebuffer_state.cbufs[i]) { 426 fprintf(f, " " COLOR_STATE "cbufs[%i]:" COLOR_RESET "\n ", i); 427 DUMP(surface, dstate->framebuffer_state.cbufs[i]); 428 fprintf(f, " "); 429 DUMP(resource, dstate->framebuffer_state.cbufs[i]->texture); 430 } 431 if (dstate->framebuffer_state.zsbuf) { 432 fprintf(f, " " COLOR_STATE "zsbuf:" COLOR_RESET "\n "); 433 DUMP(surface, dstate->framebuffer_state.zsbuf); 434 fprintf(f, " "); 435 DUMP(resource, dstate->framebuffer_state.zsbuf->texture); 436 } 437 fprintf(f, "\n"); 438} 439 440static void 441dd_dump_launch_grid(struct dd_draw_state *dstate, struct pipe_grid_info *info, FILE *f) 442{ 443 fprintf(f, "%s:\n", __func__+8); 444 DUMP(grid_info, info); 445 fprintf(f, "\n"); 446 447 dd_dump_shader(dstate, PIPE_SHADER_COMPUTE, f); 448 fprintf(f, "\n"); 449} 450 451static void 452dd_dump_resource_copy_region(struct dd_draw_state *dstate, 453 struct call_resource_copy_region *info, 454 FILE *f) 455{ 456 fprintf(f, "%s:\n", __func__+8); 457 DUMP_M(resource, info, dst); 458 DUMP_M(uint, info, dst_level); 459 DUMP_M(uint, info, dstx); 460 DUMP_M(uint, info, dsty); 461 DUMP_M(uint, info, dstz); 462 DUMP_M(resource, info, src); 463 DUMP_M(uint, info, src_level); 464 DUMP_M_ADDR(box, info, src_box); 465} 466 467static void 468dd_dump_blit(struct dd_draw_state *dstate, struct pipe_blit_info *info, FILE *f) 469{ 470 fprintf(f, "%s:\n", __func__+8); 471 DUMP_M(resource, info, dst.resource); 472 DUMP_M(uint, info, dst.level); 473 DUMP_M_ADDR(box, info, dst.box); 474 DUMP_M(format, info, dst.format); 475 476 DUMP_M(resource, info, src.resource); 477 DUMP_M(uint, info, src.level); 478 DUMP_M_ADDR(box, info, src.box); 479 DUMP_M(format, info, src.format); 480 481 DUMP_M(hex, info, mask); 482 DUMP_M(uint, info, filter); 483 DUMP_M(uint, info, scissor_enable); 484 DUMP_M_ADDR(scissor_state, info, scissor); 485 DUMP_M(uint, info, render_condition_enable); 486 487 if (info->render_condition_enable) 488 dd_dump_render_condition(dstate, f); 489} 490 491static void 492dd_dump_generate_mipmap(struct dd_draw_state *dstate, FILE *f) 493{ 494 fprintf(f, "%s:\n", __func__+8); 495 /* TODO */ 496} 497 498static void 499dd_dump_get_query_result_resource(struct call_get_query_result_resource *info, FILE *f) 500{ 501 fprintf(f, "%s:\n", __func__ + 8); 502 DUMP_M(query_type, info, query_type); 503 DUMP_M(query_flags, info, flags); 504 DUMP_M(query_value_type, info, result_type); 505 DUMP_M(int, info, index); 506 DUMP_M(resource, info, resource); 507 DUMP_M(uint, info, offset); 508} 509 510static void 511dd_dump_flush_resource(struct dd_draw_state *dstate, struct pipe_resource *res, 512 FILE *f) 513{ 514 fprintf(f, "%s:\n", __func__+8); 515 DUMP(resource, res); 516} 517 518static void 519dd_dump_clear(struct dd_draw_state *dstate, struct call_clear *info, FILE *f) 520{ 521 fprintf(f, "%s:\n", __func__+8); 522 DUMP_M(uint, info, buffers); 523 fprintf(f, " scissor_state: %d,%d %d,%d\n", 524 info->scissor_state.minx, info->scissor_state.miny, 525 info->scissor_state.maxx, info->scissor_state.maxy); 526 DUMP_M_ADDR(color_union, info, color); 527 DUMP_M(double, info, depth); 528 DUMP_M(hex, info, stencil); 529} 530 531static void 532dd_dump_clear_buffer(struct dd_draw_state *dstate, struct call_clear_buffer *info, 533 FILE *f) 534{ 535 int i; 536 const char *value = (const char*)info->clear_value; 537 538 fprintf(f, "%s:\n", __func__+8); 539 DUMP_M(resource, info, res); 540 DUMP_M(uint, info, offset); 541 DUMP_M(uint, info, size); 542 DUMP_M(uint, info, clear_value_size); 543 544 fprintf(f, " clear_value:"); 545 for (i = 0; i < info->clear_value_size; i++) 546 fprintf(f, " %02x", value[i]); 547 fprintf(f, "\n"); 548} 549 550static void 551dd_dump_transfer_map(struct call_transfer_map *info, FILE *f) 552{ 553 fprintf(f, "%s:\n", __func__+8); 554 DUMP_M_ADDR(transfer, info, transfer); 555 DUMP_M(ptr, info, transfer_ptr); 556 DUMP_M(ptr, info, ptr); 557} 558 559static void 560dd_dump_transfer_flush_region(struct call_transfer_flush_region *info, FILE *f) 561{ 562 fprintf(f, "%s:\n", __func__+8); 563 DUMP_M_ADDR(transfer, info, transfer); 564 DUMP_M(ptr, info, transfer_ptr); 565 DUMP_M_ADDR(box, info, box); 566} 567 568static void 569dd_dump_transfer_unmap(struct call_transfer_unmap *info, FILE *f) 570{ 571 fprintf(f, "%s:\n", __func__+8); 572 DUMP_M_ADDR(transfer, info, transfer); 573 DUMP_M(ptr, info, transfer_ptr); 574} 575 576static void 577dd_dump_buffer_subdata(struct call_buffer_subdata *info, FILE *f) 578{ 579 fprintf(f, "%s:\n", __func__+8); 580 DUMP_M(resource, info, resource); 581 DUMP_M(transfer_usage, info, usage); 582 DUMP_M(uint, info, offset); 583 DUMP_M(uint, info, size); 584 DUMP_M(ptr, info, data); 585} 586 587static void 588dd_dump_texture_subdata(struct call_texture_subdata *info, FILE *f) 589{ 590 fprintf(f, "%s:\n", __func__+8); 591 DUMP_M(resource, info, resource); 592 DUMP_M(uint, info, level); 593 DUMP_M(transfer_usage, info, usage); 594 DUMP_M_ADDR(box, info, box); 595 DUMP_M(ptr, info, data); 596 DUMP_M(uint, info, stride); 597 DUMP_M(uint, info, layer_stride); 598} 599 600static void 601dd_dump_clear_texture(struct dd_draw_state *dstate, FILE *f) 602{ 603 fprintf(f, "%s:\n", __func__+8); 604 /* TODO */ 605} 606 607static void 608dd_dump_clear_render_target(struct dd_draw_state *dstate, FILE *f) 609{ 610 fprintf(f, "%s:\n", __func__+8); 611 /* TODO */ 612} 613 614static void 615dd_dump_clear_depth_stencil(struct dd_draw_state *dstate, FILE *f) 616{ 617 fprintf(f, "%s:\n", __func__+8); 618 /* TODO */ 619} 620 621static void 622dd_dump_driver_state(struct dd_context *dctx, FILE *f, unsigned flags) 623{ 624 if (dctx->pipe->dump_debug_state) { 625 fprintf(f,"\n\n**************************************************" 626 "***************************\n"); 627 fprintf(f, "Driver-specific state:\n\n"); 628 dctx->pipe->dump_debug_state(dctx->pipe, f, flags); 629 } 630} 631 632static void 633dd_dump_call(FILE *f, struct dd_draw_state *state, struct dd_call *call) 634{ 635 switch (call->type) { 636 case CALL_FLUSH: 637 dd_dump_flush(state, &call->info.flush, f); 638 break; 639 case CALL_DRAW_VBO: 640 dd_dump_draw_vbo(state, &call->info.draw_vbo.info, 641 call->info.draw_vbo.drawid_offset, 642 &call->info.draw_vbo.indirect, 643 &call->info.draw_vbo.draw, f); 644 break; 645 case CALL_LAUNCH_GRID: 646 dd_dump_launch_grid(state, &call->info.launch_grid, f); 647 break; 648 case CALL_RESOURCE_COPY_REGION: 649 dd_dump_resource_copy_region(state, 650 &call->info.resource_copy_region, f); 651 break; 652 case CALL_BLIT: 653 dd_dump_blit(state, &call->info.blit, f); 654 break; 655 case CALL_FLUSH_RESOURCE: 656 dd_dump_flush_resource(state, call->info.flush_resource, f); 657 break; 658 case CALL_CLEAR: 659 dd_dump_clear(state, &call->info.clear, f); 660 break; 661 case CALL_CLEAR_BUFFER: 662 dd_dump_clear_buffer(state, &call->info.clear_buffer, f); 663 break; 664 case CALL_CLEAR_TEXTURE: 665 dd_dump_clear_texture(state, f); 666 break; 667 case CALL_CLEAR_RENDER_TARGET: 668 dd_dump_clear_render_target(state, f); 669 break; 670 case CALL_CLEAR_DEPTH_STENCIL: 671 dd_dump_clear_depth_stencil(state, f); 672 break; 673 case CALL_GENERATE_MIPMAP: 674 dd_dump_generate_mipmap(state, f); 675 break; 676 case CALL_GET_QUERY_RESULT_RESOURCE: 677 dd_dump_get_query_result_resource(&call->info.get_query_result_resource, f); 678 break; 679 case CALL_TRANSFER_MAP: 680 dd_dump_transfer_map(&call->info.transfer_map, f); 681 break; 682 case CALL_TRANSFER_FLUSH_REGION: 683 dd_dump_transfer_flush_region(&call->info.transfer_flush_region, f); 684 break; 685 case CALL_TRANSFER_UNMAP: 686 dd_dump_transfer_unmap(&call->info.transfer_unmap, f); 687 break; 688 case CALL_BUFFER_SUBDATA: 689 dd_dump_buffer_subdata(&call->info.buffer_subdata, f); 690 break; 691 case CALL_TEXTURE_SUBDATA: 692 dd_dump_texture_subdata(&call->info.texture_subdata, f); 693 break; 694 } 695} 696 697static void 698dd_kill_process(void) 699{ 700#ifdef PIPE_OS_UNIX 701 sync(); 702#endif 703 fprintf(stderr, "dd: Aborting the process...\n"); 704 fflush(stdout); 705 fflush(stderr); 706 exit(1); 707} 708 709static void 710dd_unreference_copy_of_call(struct dd_call *dst) 711{ 712 switch (dst->type) { 713 case CALL_FLUSH: 714 break; 715 case CALL_DRAW_VBO: 716 pipe_so_target_reference(&dst->info.draw_vbo.indirect.count_from_stream_output, NULL); 717 pipe_resource_reference(&dst->info.draw_vbo.indirect.buffer, NULL); 718 pipe_resource_reference(&dst->info.draw_vbo.indirect.indirect_draw_count, NULL); 719 if (dst->info.draw_vbo.info.index_size && 720 !dst->info.draw_vbo.info.has_user_indices) 721 pipe_resource_reference(&dst->info.draw_vbo.info.index.resource, NULL); 722 else 723 dst->info.draw_vbo.info.index.user = NULL; 724 break; 725 case CALL_LAUNCH_GRID: 726 pipe_resource_reference(&dst->info.launch_grid.indirect, NULL); 727 break; 728 case CALL_RESOURCE_COPY_REGION: 729 pipe_resource_reference(&dst->info.resource_copy_region.dst, NULL); 730 pipe_resource_reference(&dst->info.resource_copy_region.src, NULL); 731 break; 732 case CALL_BLIT: 733 pipe_resource_reference(&dst->info.blit.dst.resource, NULL); 734 pipe_resource_reference(&dst->info.blit.src.resource, NULL); 735 break; 736 case CALL_FLUSH_RESOURCE: 737 pipe_resource_reference(&dst->info.flush_resource, NULL); 738 break; 739 case CALL_CLEAR: 740 break; 741 case CALL_CLEAR_BUFFER: 742 pipe_resource_reference(&dst->info.clear_buffer.res, NULL); 743 break; 744 case CALL_CLEAR_TEXTURE: 745 break; 746 case CALL_CLEAR_RENDER_TARGET: 747 break; 748 case CALL_CLEAR_DEPTH_STENCIL: 749 break; 750 case CALL_GENERATE_MIPMAP: 751 pipe_resource_reference(&dst->info.generate_mipmap.res, NULL); 752 break; 753 case CALL_GET_QUERY_RESULT_RESOURCE: 754 pipe_resource_reference(&dst->info.get_query_result_resource.resource, NULL); 755 break; 756 case CALL_TRANSFER_MAP: 757 pipe_resource_reference(&dst->info.transfer_map.transfer.resource, NULL); 758 break; 759 case CALL_TRANSFER_FLUSH_REGION: 760 pipe_resource_reference(&dst->info.transfer_flush_region.transfer.resource, NULL); 761 break; 762 case CALL_TRANSFER_UNMAP: 763 pipe_resource_reference(&dst->info.transfer_unmap.transfer.resource, NULL); 764 break; 765 case CALL_BUFFER_SUBDATA: 766 pipe_resource_reference(&dst->info.buffer_subdata.resource, NULL); 767 break; 768 case CALL_TEXTURE_SUBDATA: 769 pipe_resource_reference(&dst->info.texture_subdata.resource, NULL); 770 break; 771 } 772} 773 774static void 775dd_init_copy_of_draw_state(struct dd_draw_state_copy *state) 776{ 777 unsigned i,j; 778 779 /* Just clear pointers to gallium objects. Don't clear the whole structure, 780 * because it would kill performance with its size of 130 KB. 781 */ 782 memset(state->base.vertex_buffers, 0, 783 sizeof(state->base.vertex_buffers)); 784 memset(state->base.so_targets, 0, 785 sizeof(state->base.so_targets)); 786 memset(state->base.constant_buffers, 0, 787 sizeof(state->base.constant_buffers)); 788 memset(state->base.sampler_views, 0, 789 sizeof(state->base.sampler_views)); 790 memset(state->base.shader_images, 0, 791 sizeof(state->base.shader_images)); 792 memset(state->base.shader_buffers, 0, 793 sizeof(state->base.shader_buffers)); 794 memset(&state->base.framebuffer_state, 0, 795 sizeof(state->base.framebuffer_state)); 796 797 memset(state->shaders, 0, sizeof(state->shaders)); 798 799 state->base.render_cond.query = &state->render_cond; 800 801 for (i = 0; i < PIPE_SHADER_TYPES; i++) { 802 state->base.shaders[i] = &state->shaders[i]; 803 for (j = 0; j < PIPE_MAX_SAMPLERS; j++) 804 state->base.sampler_states[i][j] = &state->sampler_states[i][j]; 805 } 806 807 state->base.velems = &state->velems; 808 state->base.rs = &state->rs; 809 state->base.dsa = &state->dsa; 810 state->base.blend = &state->blend; 811} 812 813static void 814dd_unreference_copy_of_draw_state(struct dd_draw_state_copy *state) 815{ 816 struct dd_draw_state *dst = &state->base; 817 unsigned i,j; 818 819 for (i = 0; i < ARRAY_SIZE(dst->vertex_buffers); i++) 820 pipe_vertex_buffer_unreference(&dst->vertex_buffers[i]); 821 for (i = 0; i < ARRAY_SIZE(dst->so_targets); i++) 822 pipe_so_target_reference(&dst->so_targets[i], NULL); 823 824 for (i = 0; i < PIPE_SHADER_TYPES; i++) { 825 if (dst->shaders[i]) 826 tgsi_free_tokens(dst->shaders[i]->state.shader.tokens); 827 828 for (j = 0; j < PIPE_MAX_CONSTANT_BUFFERS; j++) 829 pipe_resource_reference(&dst->constant_buffers[i][j].buffer, NULL); 830 for (j = 0; j < PIPE_MAX_SAMPLERS; j++) 831 pipe_sampler_view_reference(&dst->sampler_views[i][j], NULL); 832 for (j = 0; j < PIPE_MAX_SHADER_IMAGES; j++) 833 pipe_resource_reference(&dst->shader_images[i][j].resource, NULL); 834 for (j = 0; j < PIPE_MAX_SHADER_BUFFERS; j++) 835 pipe_resource_reference(&dst->shader_buffers[i][j].buffer, NULL); 836 } 837 838 util_unreference_framebuffer_state(&dst->framebuffer_state); 839} 840 841static void 842dd_copy_draw_state(struct dd_draw_state *dst, struct dd_draw_state *src) 843{ 844 unsigned i,j; 845 846 if (src->render_cond.query) { 847 *dst->render_cond.query = *src->render_cond.query; 848 dst->render_cond.condition = src->render_cond.condition; 849 dst->render_cond.mode = src->render_cond.mode; 850 } else { 851 dst->render_cond.query = NULL; 852 } 853 854 for (i = 0; i < ARRAY_SIZE(src->vertex_buffers); i++) { 855 pipe_vertex_buffer_reference(&dst->vertex_buffers[i], 856 &src->vertex_buffers[i]); 857 } 858 859 dst->num_so_targets = src->num_so_targets; 860 for (i = 0; i < src->num_so_targets; i++) 861 pipe_so_target_reference(&dst->so_targets[i], src->so_targets[i]); 862 memcpy(dst->so_offsets, src->so_offsets, sizeof(src->so_offsets)); 863 864 for (i = 0; i < PIPE_SHADER_TYPES; i++) { 865 if (!src->shaders[i]) { 866 dst->shaders[i] = NULL; 867 continue; 868 } 869 870 if (src->shaders[i]) { 871 dst->shaders[i]->state.shader = src->shaders[i]->state.shader; 872 if (src->shaders[i]->state.shader.tokens) { 873 dst->shaders[i]->state.shader.tokens = 874 tgsi_dup_tokens(src->shaders[i]->state.shader.tokens); 875 } else { 876 dst->shaders[i]->state.shader.ir.nir = NULL; 877 } 878 } else { 879 dst->shaders[i] = NULL; 880 } 881 882 for (j = 0; j < PIPE_MAX_CONSTANT_BUFFERS; j++) { 883 pipe_resource_reference(&dst->constant_buffers[i][j].buffer, 884 src->constant_buffers[i][j].buffer); 885 memcpy(&dst->constant_buffers[i][j], &src->constant_buffers[i][j], 886 sizeof(src->constant_buffers[i][j])); 887 } 888 889 for (j = 0; j < PIPE_MAX_SAMPLERS; j++) { 890 pipe_sampler_view_reference(&dst->sampler_views[i][j], 891 src->sampler_views[i][j]); 892 if (src->sampler_states[i][j]) 893 dst->sampler_states[i][j]->state.sampler = 894 src->sampler_states[i][j]->state.sampler; 895 else 896 dst->sampler_states[i][j] = NULL; 897 } 898 899 for (j = 0; j < PIPE_MAX_SHADER_IMAGES; j++) { 900 pipe_resource_reference(&dst->shader_images[i][j].resource, 901 src->shader_images[i][j].resource); 902 memcpy(&dst->shader_images[i][j], &src->shader_images[i][j], 903 sizeof(src->shader_images[i][j])); 904 } 905 906 for (j = 0; j < PIPE_MAX_SHADER_BUFFERS; j++) { 907 pipe_resource_reference(&dst->shader_buffers[i][j].buffer, 908 src->shader_buffers[i][j].buffer); 909 memcpy(&dst->shader_buffers[i][j], &src->shader_buffers[i][j], 910 sizeof(src->shader_buffers[i][j])); 911 } 912 } 913 914 if (src->velems) 915 dst->velems->state.velems = src->velems->state.velems; 916 else 917 dst->velems = NULL; 918 919 if (src->rs) 920 dst->rs->state.rs = src->rs->state.rs; 921 else 922 dst->rs = NULL; 923 924 if (src->dsa) 925 dst->dsa->state.dsa = src->dsa->state.dsa; 926 else 927 dst->dsa = NULL; 928 929 if (src->blend) 930 dst->blend->state.blend = src->blend->state.blend; 931 else 932 dst->blend = NULL; 933 934 dst->blend_color = src->blend_color; 935 dst->stencil_ref = src->stencil_ref; 936 dst->sample_mask = src->sample_mask; 937 dst->min_samples = src->min_samples; 938 dst->clip_state = src->clip_state; 939 util_copy_framebuffer_state(&dst->framebuffer_state, &src->framebuffer_state); 940 memcpy(dst->scissors, src->scissors, sizeof(src->scissors)); 941 memcpy(dst->viewports, src->viewports, sizeof(src->viewports)); 942 memcpy(dst->tess_default_levels, src->tess_default_levels, 943 sizeof(src->tess_default_levels)); 944 dst->apitrace_call_number = src->apitrace_call_number; 945} 946 947static void 948dd_free_record(struct pipe_screen *screen, struct dd_draw_record *record) 949{ 950 u_log_page_destroy(record->log_page); 951 dd_unreference_copy_of_call(&record->call); 952 dd_unreference_copy_of_draw_state(&record->draw_state); 953 screen->fence_reference(screen, &record->prev_bottom_of_pipe, NULL); 954 screen->fence_reference(screen, &record->top_of_pipe, NULL); 955 screen->fence_reference(screen, &record->bottom_of_pipe, NULL); 956 util_queue_fence_destroy(&record->driver_finished); 957 FREE(record); 958} 959 960static void 961dd_write_record(FILE *f, struct dd_draw_record *record) 962{ 963 PRINT_NAMED(ptr, "pipe", record->dctx->pipe); 964 PRINT_NAMED(ns, "time before (API call)", record->time_before); 965 PRINT_NAMED(ns, "time after (driver done)", record->time_after); 966 fprintf(f, "\n"); 967 968 dd_dump_call(f, &record->draw_state.base, &record->call); 969 970 if (record->log_page) { 971 fprintf(f,"\n\n**************************************************" 972 "***************************\n"); 973 fprintf(f, "Context Log:\n\n"); 974 u_log_page_print(record->log_page, f); 975 } 976} 977 978static void 979dd_maybe_dump_record(struct dd_screen *dscreen, struct dd_draw_record *record) 980{ 981 if (dscreen->dump_mode == DD_DUMP_ONLY_HANGS || 982 (dscreen->dump_mode == DD_DUMP_APITRACE_CALL && 983 dscreen->apitrace_dump_call != record->draw_state.base.apitrace_call_number)) 984 return; 985 986 char name[512]; 987 dd_get_debug_filename_and_mkdir(name, sizeof(name), dscreen->verbose); 988 FILE *f = fopen(name, "w"); 989 if (!f) { 990 fprintf(stderr, "dd: failed to open %s\n", name); 991 return; 992 } 993 994 dd_write_header(f, dscreen->screen, record->draw_state.base.apitrace_call_number); 995 dd_write_record(f, record); 996 997 fclose(f); 998} 999 1000static const char * 1001dd_fence_state(struct pipe_screen *screen, struct pipe_fence_handle *fence, 1002 bool *not_reached) 1003{ 1004 if (!fence) 1005 return "---"; 1006 1007 bool ok = screen->fence_finish(screen, NULL, fence, 0); 1008 1009 if (not_reached && !ok) 1010 *not_reached = true; 1011 1012 return ok ? "YES" : "NO "; 1013} 1014 1015static void 1016dd_report_hang(struct dd_context *dctx) 1017{ 1018 struct dd_screen *dscreen = dd_screen(dctx->base.screen); 1019 struct pipe_screen *screen = dscreen->screen; 1020 bool encountered_hang = false; 1021 bool stop_output = false; 1022 unsigned num_later = 0; 1023 1024 fprintf(stderr, "GPU hang detected, collecting information...\n\n"); 1025 1026 fprintf(stderr, "Draw # driver prev BOP TOP BOP dump file\n" 1027 "-------------------------------------------------------------\n"); 1028 1029 list_for_each_entry(struct dd_draw_record, record, &dctx->records, list) { 1030 if (!encountered_hang && 1031 screen->fence_finish(screen, NULL, record->bottom_of_pipe, 0)) { 1032 dd_maybe_dump_record(dscreen, record); 1033 continue; 1034 } 1035 1036 if (stop_output) { 1037 dd_maybe_dump_record(dscreen, record); 1038 num_later++; 1039 continue; 1040 } 1041 1042 bool driver = util_queue_fence_is_signalled(&record->driver_finished); 1043 bool top_not_reached = false; 1044 const char *prev_bop = dd_fence_state(screen, record->prev_bottom_of_pipe, NULL); 1045 const char *top = dd_fence_state(screen, record->top_of_pipe, &top_not_reached); 1046 const char *bop = dd_fence_state(screen, record->bottom_of_pipe, NULL); 1047 1048 fprintf(stderr, "%-9u %s %s %s %s ", 1049 record->draw_call, driver ? "YES" : "NO ", prev_bop, top, bop); 1050 1051 char name[512]; 1052 dd_get_debug_filename_and_mkdir(name, sizeof(name), false); 1053 1054 FILE *f = fopen(name, "w"); 1055 if (!f) { 1056 fprintf(stderr, "fopen failed\n"); 1057 } else { 1058 fprintf(stderr, "%s\n", name); 1059 1060 dd_write_header(f, dscreen->screen, record->draw_state.base.apitrace_call_number); 1061 dd_write_record(f, record); 1062 1063 fclose(f); 1064 } 1065 1066 if (top_not_reached) 1067 stop_output = true; 1068 encountered_hang = true; 1069 } 1070 1071 if (num_later) 1072 fprintf(stderr, "... and %u additional draws.\n", num_later); 1073 1074 char name[512]; 1075 dd_get_debug_filename_and_mkdir(name, sizeof(name), false); 1076 FILE *f = fopen(name, "w"); 1077 if (!f) { 1078 fprintf(stderr, "fopen failed\n"); 1079 } else { 1080 dd_write_header(f, dscreen->screen, 0); 1081 dd_dump_driver_state(dctx, f, PIPE_DUMP_DEVICE_STATUS_REGISTERS); 1082 dd_dump_dmesg(f); 1083 fclose(f); 1084 } 1085 1086 fprintf(stderr, "\nDone.\n"); 1087 dd_kill_process(); 1088} 1089 1090int 1091dd_thread_main(void *input) 1092{ 1093 struct dd_context *dctx = (struct dd_context *)input; 1094 struct dd_screen *dscreen = dd_screen(dctx->base.screen); 1095 struct pipe_screen *screen = dscreen->screen; 1096 1097 const char *process_name = util_get_process_name(); 1098 if (process_name) { 1099 char threadname[16]; 1100 snprintf(threadname, sizeof(threadname), "%.*s:ddbg", 1101 (int)MIN2(strlen(process_name), sizeof(threadname) - 6), 1102 process_name); 1103 u_thread_setname(threadname); 1104 } 1105 1106 mtx_lock(&dctx->mutex); 1107 1108 for (;;) { 1109 struct list_head records; 1110 list_replace(&dctx->records, &records); 1111 list_inithead(&dctx->records); 1112 dctx->num_records = 0; 1113 1114 if (dctx->api_stalled) 1115 cnd_signal(&dctx->cond); 1116 1117 if (list_is_empty(&records)) { 1118 if (dctx->kill_thread) 1119 break; 1120 1121 cnd_wait(&dctx->cond, &dctx->mutex); 1122 continue; 1123 } 1124 1125 mtx_unlock(&dctx->mutex); 1126 1127 /* Wait for the youngest draw. This means hangs can take a bit longer 1128 * to detect, but it's more efficient this way. */ 1129 struct dd_draw_record *youngest = 1130 list_last_entry(&records, struct dd_draw_record, list); 1131 1132 if (dscreen->timeout_ms > 0) { 1133 uint64_t abs_timeout = os_time_get_absolute_timeout( 1134 (uint64_t)dscreen->timeout_ms * 1000*1000); 1135 1136 if (!util_queue_fence_wait_timeout(&youngest->driver_finished, abs_timeout) || 1137 !screen->fence_finish(screen, NULL, youngest->bottom_of_pipe, 1138 (uint64_t)dscreen->timeout_ms * 1000*1000)) { 1139 mtx_lock(&dctx->mutex); 1140 list_splice(&records, &dctx->records); 1141 dd_report_hang(dctx); 1142 /* we won't actually get here */ 1143 mtx_unlock(&dctx->mutex); 1144 } 1145 } else { 1146 util_queue_fence_wait(&youngest->driver_finished); 1147 } 1148 1149 list_for_each_entry_safe(struct dd_draw_record, record, &records, list) { 1150 dd_maybe_dump_record(dscreen, record); 1151 list_del(&record->list); 1152 dd_free_record(screen, record); 1153 } 1154 1155 mtx_lock(&dctx->mutex); 1156 } 1157 mtx_unlock(&dctx->mutex); 1158 return 0; 1159} 1160 1161static struct dd_draw_record * 1162dd_create_record(struct dd_context *dctx) 1163{ 1164 struct dd_draw_record *record; 1165 1166 record = MALLOC_STRUCT(dd_draw_record); 1167 if (!record) 1168 return NULL; 1169 1170 record->dctx = dctx; 1171 record->draw_call = dctx->num_draw_calls; 1172 1173 record->prev_bottom_of_pipe = NULL; 1174 record->top_of_pipe = NULL; 1175 record->bottom_of_pipe = NULL; 1176 record->log_page = NULL; 1177 util_queue_fence_init(&record->driver_finished); 1178 util_queue_fence_reset(&record->driver_finished); 1179 1180 dd_init_copy_of_draw_state(&record->draw_state); 1181 dd_copy_draw_state(&record->draw_state.base, &dctx->draw_state); 1182 1183 return record; 1184} 1185 1186static void 1187dd_add_record(struct dd_context *dctx, struct dd_draw_record *record) 1188{ 1189 mtx_lock(&dctx->mutex); 1190 if (unlikely(dctx->num_records > 10000)) { 1191 dctx->api_stalled = true; 1192 /* Since this is only a heuristic to prevent the API thread from getting 1193 * too far ahead, we don't need a loop here. */ 1194 cnd_wait(&dctx->cond, &dctx->mutex); 1195 dctx->api_stalled = false; 1196 } 1197 1198 if (list_is_empty(&dctx->records)) 1199 cnd_signal(&dctx->cond); 1200 1201 list_addtail(&record->list, &dctx->records); 1202 dctx->num_records++; 1203 mtx_unlock(&dctx->mutex); 1204} 1205 1206static void 1207dd_before_draw(struct dd_context *dctx, struct dd_draw_record *record) 1208{ 1209 struct dd_screen *dscreen = dd_screen(dctx->base.screen); 1210 struct pipe_context *pipe = dctx->pipe; 1211 struct pipe_screen *screen = dscreen->screen; 1212 1213 record->time_before = os_time_get_nano(); 1214 1215 if (dscreen->timeout_ms > 0) { 1216 if (dscreen->flush_always && dctx->num_draw_calls >= dscreen->skip_count) { 1217 pipe->flush(pipe, &record->prev_bottom_of_pipe, 0); 1218 screen->fence_reference(screen, &record->top_of_pipe, record->prev_bottom_of_pipe); 1219 } else { 1220 pipe->flush(pipe, &record->prev_bottom_of_pipe, 1221 PIPE_FLUSH_DEFERRED | PIPE_FLUSH_BOTTOM_OF_PIPE); 1222 pipe->flush(pipe, &record->top_of_pipe, 1223 PIPE_FLUSH_DEFERRED | PIPE_FLUSH_TOP_OF_PIPE); 1224 } 1225 } else if (dscreen->flush_always && dctx->num_draw_calls >= dscreen->skip_count) { 1226 pipe->flush(pipe, NULL, 0); 1227 } 1228 1229 dd_add_record(dctx, record); 1230} 1231 1232static void 1233dd_after_draw_async(void *data) 1234{ 1235 struct dd_draw_record *record = (struct dd_draw_record *)data; 1236 struct dd_context *dctx = record->dctx; 1237 struct dd_screen *dscreen = dd_screen(dctx->base.screen); 1238 1239 record->log_page = u_log_new_page(&dctx->log); 1240 record->time_after = os_time_get_nano(); 1241 1242 util_queue_fence_signal(&record->driver_finished); 1243 1244 if (dscreen->dump_mode == DD_DUMP_APITRACE_CALL && 1245 dscreen->apitrace_dump_call > dctx->draw_state.apitrace_call_number) { 1246 dd_thread_join(dctx); 1247 /* No need to continue. */ 1248 exit(0); 1249 } 1250} 1251 1252static void 1253dd_after_draw(struct dd_context *dctx, struct dd_draw_record *record) 1254{ 1255 struct dd_screen *dscreen = dd_screen(dctx->base.screen); 1256 struct pipe_context *pipe = dctx->pipe; 1257 1258 if (dscreen->timeout_ms > 0) { 1259 unsigned flush_flags; 1260 if (dscreen->flush_always && dctx->num_draw_calls >= dscreen->skip_count) 1261 flush_flags = 0; 1262 else 1263 flush_flags = PIPE_FLUSH_DEFERRED | PIPE_FLUSH_BOTTOM_OF_PIPE; 1264 pipe->flush(pipe, &record->bottom_of_pipe, flush_flags); 1265 } 1266 1267 if (pipe->callback) { 1268 pipe->callback(pipe, dd_after_draw_async, record, true); 1269 } else { 1270 dd_after_draw_async(record); 1271 } 1272 1273 ++dctx->num_draw_calls; 1274 if (dscreen->skip_count && dctx->num_draw_calls % 10000 == 0) 1275 fprintf(stderr, "Gallium debugger reached %u draw calls.\n", 1276 dctx->num_draw_calls); 1277} 1278 1279static void 1280dd_context_flush(struct pipe_context *_pipe, 1281 struct pipe_fence_handle **fence, unsigned flags) 1282{ 1283 struct dd_context *dctx = dd_context(_pipe); 1284 struct pipe_context *pipe = dctx->pipe; 1285 struct pipe_screen *screen = pipe->screen; 1286 struct dd_draw_record *record = dd_create_record(dctx); 1287 1288 record->call.type = CALL_FLUSH; 1289 record->call.info.flush.flags = flags; 1290 1291 record->time_before = os_time_get_nano(); 1292 1293 dd_add_record(dctx, record); 1294 1295 pipe->flush(pipe, &record->bottom_of_pipe, flags); 1296 if (fence) 1297 screen->fence_reference(screen, fence, record->bottom_of_pipe); 1298 1299 if (pipe->callback) { 1300 pipe->callback(pipe, dd_after_draw_async, record, true); 1301 } else { 1302 dd_after_draw_async(record); 1303 } 1304} 1305 1306static void 1307dd_context_draw_vbo(struct pipe_context *_pipe, 1308 const struct pipe_draw_info *info, 1309 unsigned drawid_offset, 1310 const struct pipe_draw_indirect_info *indirect, 1311 const struct pipe_draw_start_count_bias *draws, 1312 unsigned num_draws) 1313{ 1314 struct dd_context *dctx = dd_context(_pipe); 1315 struct pipe_context *pipe = dctx->pipe; 1316 struct dd_draw_record *record = dd_create_record(dctx); 1317 1318 record->call.type = CALL_DRAW_VBO; 1319 record->call.info.draw_vbo.info = *info; 1320 record->call.info.draw_vbo.drawid_offset = drawid_offset; 1321 record->call.info.draw_vbo.draw = draws[0]; 1322 if (info->index_size && !info->has_user_indices) { 1323 record->call.info.draw_vbo.info.index.resource = NULL; 1324 pipe_resource_reference(&record->call.info.draw_vbo.info.index.resource, 1325 info->index.resource); 1326 } 1327 1328 if (indirect) { 1329 record->call.info.draw_vbo.indirect = *indirect; 1330 record->call.info.draw_vbo.indirect.buffer = NULL; 1331 pipe_resource_reference(&record->call.info.draw_vbo.indirect.buffer, 1332 indirect->buffer); 1333 record->call.info.draw_vbo.indirect.indirect_draw_count = NULL; 1334 pipe_resource_reference(&record->call.info.draw_vbo.indirect.indirect_draw_count, 1335 indirect->indirect_draw_count); 1336 record->call.info.draw_vbo.indirect.count_from_stream_output = NULL; 1337 pipe_so_target_reference(&record->call.info.draw_vbo.indirect.count_from_stream_output, 1338 indirect->count_from_stream_output); 1339 } else { 1340 memset(&record->call.info.draw_vbo.indirect, 0, sizeof(*indirect)); 1341 } 1342 1343 dd_before_draw(dctx, record); 1344 pipe->draw_vbo(pipe, info, drawid_offset, indirect, draws, num_draws); 1345 dd_after_draw(dctx, record); 1346} 1347 1348static void 1349dd_context_draw_vertex_state(struct pipe_context *_pipe, 1350 struct pipe_vertex_state *state, 1351 uint32_t partial_velem_mask, 1352 struct pipe_draw_vertex_state_info info, 1353 const struct pipe_draw_start_count_bias *draws, 1354 unsigned num_draws) 1355{ 1356 struct dd_context *dctx = dd_context(_pipe); 1357 struct pipe_context *pipe = dctx->pipe; 1358 struct dd_draw_record *record = dd_create_record(dctx); 1359 1360 record->call.type = CALL_DRAW_VBO; 1361 memset(&record->call.info.draw_vbo.info, 0, 1362 sizeof(record->call.info.draw_vbo.info)); 1363 record->call.info.draw_vbo.info.mode = info.mode; 1364 record->call.info.draw_vbo.info.index_size = 4; 1365 record->call.info.draw_vbo.info.instance_count = 1; 1366 record->call.info.draw_vbo.drawid_offset = 0; 1367 record->call.info.draw_vbo.draw = draws[0]; 1368 record->call.info.draw_vbo.info.index.resource = NULL; 1369 pipe_resource_reference(&record->call.info.draw_vbo.info.index.resource, 1370 state->input.indexbuf); 1371 memset(&record->call.info.draw_vbo.indirect, 0, 1372 sizeof(record->call.info.draw_vbo.indirect)); 1373 1374 dd_before_draw(dctx, record); 1375 pipe->draw_vertex_state(pipe, state, partial_velem_mask, info, draws, num_draws); 1376 dd_after_draw(dctx, record); 1377} 1378 1379static void 1380dd_context_launch_grid(struct pipe_context *_pipe, 1381 const struct pipe_grid_info *info) 1382{ 1383 struct dd_context *dctx = dd_context(_pipe); 1384 struct pipe_context *pipe = dctx->pipe; 1385 struct dd_draw_record *record = dd_create_record(dctx); 1386 1387 record->call.type = CALL_LAUNCH_GRID; 1388 record->call.info.launch_grid = *info; 1389 record->call.info.launch_grid.indirect = NULL; 1390 pipe_resource_reference(&record->call.info.launch_grid.indirect, info->indirect); 1391 1392 dd_before_draw(dctx, record); 1393 pipe->launch_grid(pipe, info); 1394 dd_after_draw(dctx, record); 1395} 1396 1397static void 1398dd_context_resource_copy_region(struct pipe_context *_pipe, 1399 struct pipe_resource *dst, unsigned dst_level, 1400 unsigned dstx, unsigned dsty, unsigned dstz, 1401 struct pipe_resource *src, unsigned src_level, 1402 const struct pipe_box *src_box) 1403{ 1404 struct dd_context *dctx = dd_context(_pipe); 1405 struct pipe_context *pipe = dctx->pipe; 1406 struct dd_draw_record *record = dd_create_record(dctx); 1407 1408 record->call.type = CALL_RESOURCE_COPY_REGION; 1409 record->call.info.resource_copy_region.dst = NULL; 1410 pipe_resource_reference(&record->call.info.resource_copy_region.dst, dst); 1411 record->call.info.resource_copy_region.dst_level = dst_level; 1412 record->call.info.resource_copy_region.dstx = dstx; 1413 record->call.info.resource_copy_region.dsty = dsty; 1414 record->call.info.resource_copy_region.dstz = dstz; 1415 record->call.info.resource_copy_region.src = NULL; 1416 pipe_resource_reference(&record->call.info.resource_copy_region.src, src); 1417 record->call.info.resource_copy_region.src_level = src_level; 1418 record->call.info.resource_copy_region.src_box = *src_box; 1419 1420 dd_before_draw(dctx, record); 1421 pipe->resource_copy_region(pipe, 1422 dst, dst_level, dstx, dsty, dstz, 1423 src, src_level, src_box); 1424 dd_after_draw(dctx, record); 1425} 1426 1427static void 1428dd_context_blit(struct pipe_context *_pipe, const struct pipe_blit_info *info) 1429{ 1430 struct dd_context *dctx = dd_context(_pipe); 1431 struct pipe_context *pipe = dctx->pipe; 1432 struct dd_draw_record *record = dd_create_record(dctx); 1433 1434 record->call.type = CALL_BLIT; 1435 record->call.info.blit = *info; 1436 record->call.info.blit.dst.resource = NULL; 1437 pipe_resource_reference(&record->call.info.blit.dst.resource, info->dst.resource); 1438 record->call.info.blit.src.resource = NULL; 1439 pipe_resource_reference(&record->call.info.blit.src.resource, info->src.resource); 1440 1441 dd_before_draw(dctx, record); 1442 pipe->blit(pipe, info); 1443 dd_after_draw(dctx, record); 1444} 1445 1446static bool 1447dd_context_generate_mipmap(struct pipe_context *_pipe, 1448 struct pipe_resource *res, 1449 enum pipe_format format, 1450 unsigned base_level, 1451 unsigned last_level, 1452 unsigned first_layer, 1453 unsigned last_layer) 1454{ 1455 struct dd_context *dctx = dd_context(_pipe); 1456 struct pipe_context *pipe = dctx->pipe; 1457 struct dd_draw_record *record = dd_create_record(dctx); 1458 bool result; 1459 1460 record->call.type = CALL_GENERATE_MIPMAP; 1461 record->call.info.generate_mipmap.res = NULL; 1462 pipe_resource_reference(&record->call.info.generate_mipmap.res, res); 1463 record->call.info.generate_mipmap.format = format; 1464 record->call.info.generate_mipmap.base_level = base_level; 1465 record->call.info.generate_mipmap.last_level = last_level; 1466 record->call.info.generate_mipmap.first_layer = first_layer; 1467 record->call.info.generate_mipmap.last_layer = last_layer; 1468 1469 dd_before_draw(dctx, record); 1470 result = pipe->generate_mipmap(pipe, res, format, base_level, last_level, 1471 first_layer, last_layer); 1472 dd_after_draw(dctx, record); 1473 return result; 1474} 1475 1476static void 1477dd_context_get_query_result_resource(struct pipe_context *_pipe, 1478 struct pipe_query *query, 1479 enum pipe_query_flags flags, 1480 enum pipe_query_value_type result_type, 1481 int index, 1482 struct pipe_resource *resource, 1483 unsigned offset) 1484{ 1485 struct dd_context *dctx = dd_context(_pipe); 1486 struct dd_query *dquery = dd_query(query); 1487 struct pipe_context *pipe = dctx->pipe; 1488 struct dd_draw_record *record = dd_create_record(dctx); 1489 1490 record->call.type = CALL_GET_QUERY_RESULT_RESOURCE; 1491 record->call.info.get_query_result_resource.query = query; 1492 record->call.info.get_query_result_resource.flags = flags; 1493 record->call.info.get_query_result_resource.result_type = result_type; 1494 record->call.info.get_query_result_resource.index = index; 1495 record->call.info.get_query_result_resource.resource = NULL; 1496 pipe_resource_reference(&record->call.info.get_query_result_resource.resource, 1497 resource); 1498 record->call.info.get_query_result_resource.offset = offset; 1499 1500 /* The query may be deleted by the time we need to print it. */ 1501 record->call.info.get_query_result_resource.query_type = dquery->type; 1502 1503 dd_before_draw(dctx, record); 1504 pipe->get_query_result_resource(pipe, dquery->query, flags, 1505 result_type, index, resource, offset); 1506 dd_after_draw(dctx, record); 1507} 1508 1509static void 1510dd_context_flush_resource(struct pipe_context *_pipe, 1511 struct pipe_resource *resource) 1512{ 1513 struct dd_context *dctx = dd_context(_pipe); 1514 struct pipe_context *pipe = dctx->pipe; 1515 struct dd_draw_record *record = dd_create_record(dctx); 1516 1517 record->call.type = CALL_FLUSH_RESOURCE; 1518 record->call.info.flush_resource = NULL; 1519 pipe_resource_reference(&record->call.info.flush_resource, resource); 1520 1521 dd_before_draw(dctx, record); 1522 pipe->flush_resource(pipe, resource); 1523 dd_after_draw(dctx, record); 1524} 1525 1526static void 1527dd_context_clear(struct pipe_context *_pipe, unsigned buffers, const struct pipe_scissor_state *scissor_state, 1528 const union pipe_color_union *color, double depth, 1529 unsigned stencil) 1530{ 1531 struct dd_context *dctx = dd_context(_pipe); 1532 struct pipe_context *pipe = dctx->pipe; 1533 struct dd_draw_record *record = dd_create_record(dctx); 1534 1535 record->call.type = CALL_CLEAR; 1536 record->call.info.clear.buffers = buffers; 1537 if (scissor_state) 1538 record->call.info.clear.scissor_state = *scissor_state; 1539 record->call.info.clear.color = *color; 1540 record->call.info.clear.depth = depth; 1541 record->call.info.clear.stencil = stencil; 1542 1543 dd_before_draw(dctx, record); 1544 pipe->clear(pipe, buffers, scissor_state, color, depth, stencil); 1545 dd_after_draw(dctx, record); 1546} 1547 1548static void 1549dd_context_clear_render_target(struct pipe_context *_pipe, 1550 struct pipe_surface *dst, 1551 const union pipe_color_union *color, 1552 unsigned dstx, unsigned dsty, 1553 unsigned width, unsigned height, 1554 bool render_condition_enabled) 1555{ 1556 struct dd_context *dctx = dd_context(_pipe); 1557 struct pipe_context *pipe = dctx->pipe; 1558 struct dd_draw_record *record = dd_create_record(dctx); 1559 1560 record->call.type = CALL_CLEAR_RENDER_TARGET; 1561 1562 dd_before_draw(dctx, record); 1563 pipe->clear_render_target(pipe, dst, color, dstx, dsty, width, height, 1564 render_condition_enabled); 1565 dd_after_draw(dctx, record); 1566} 1567 1568static void 1569dd_context_clear_depth_stencil(struct pipe_context *_pipe, 1570 struct pipe_surface *dst, unsigned clear_flags, 1571 double depth, unsigned stencil, unsigned dstx, 1572 unsigned dsty, unsigned width, unsigned height, 1573 bool render_condition_enabled) 1574{ 1575 struct dd_context *dctx = dd_context(_pipe); 1576 struct pipe_context *pipe = dctx->pipe; 1577 struct dd_draw_record *record = dd_create_record(dctx); 1578 1579 record->call.type = CALL_CLEAR_DEPTH_STENCIL; 1580 1581 dd_before_draw(dctx, record); 1582 pipe->clear_depth_stencil(pipe, dst, clear_flags, depth, stencil, 1583 dstx, dsty, width, height, 1584 render_condition_enabled); 1585 dd_after_draw(dctx, record); 1586} 1587 1588static void 1589dd_context_clear_buffer(struct pipe_context *_pipe, struct pipe_resource *res, 1590 unsigned offset, unsigned size, 1591 const void *clear_value, int clear_value_size) 1592{ 1593 struct dd_context *dctx = dd_context(_pipe); 1594 struct pipe_context *pipe = dctx->pipe; 1595 struct dd_draw_record *record = dd_create_record(dctx); 1596 1597 record->call.type = CALL_CLEAR_BUFFER; 1598 record->call.info.clear_buffer.res = NULL; 1599 pipe_resource_reference(&record->call.info.clear_buffer.res, res); 1600 record->call.info.clear_buffer.offset = offset; 1601 record->call.info.clear_buffer.size = size; 1602 record->call.info.clear_buffer.clear_value = clear_value; 1603 record->call.info.clear_buffer.clear_value_size = clear_value_size; 1604 1605 dd_before_draw(dctx, record); 1606 pipe->clear_buffer(pipe, res, offset, size, clear_value, clear_value_size); 1607 dd_after_draw(dctx, record); 1608} 1609 1610static void 1611dd_context_clear_texture(struct pipe_context *_pipe, 1612 struct pipe_resource *res, 1613 unsigned level, 1614 const struct pipe_box *box, 1615 const void *data) 1616{ 1617 struct dd_context *dctx = dd_context(_pipe); 1618 struct pipe_context *pipe = dctx->pipe; 1619 struct dd_draw_record *record = dd_create_record(dctx); 1620 1621 record->call.type = CALL_CLEAR_TEXTURE; 1622 1623 dd_before_draw(dctx, record); 1624 pipe->clear_texture(pipe, res, level, box, data); 1625 dd_after_draw(dctx, record); 1626} 1627 1628/******************************************************************** 1629 * transfer 1630 */ 1631 1632static void * 1633dd_context_buffer_map(struct pipe_context *_pipe, 1634 struct pipe_resource *resource, unsigned level, 1635 unsigned usage, const struct pipe_box *box, 1636 struct pipe_transfer **transfer) 1637{ 1638 struct dd_context *dctx = dd_context(_pipe); 1639 struct pipe_context *pipe = dctx->pipe; 1640 struct dd_draw_record *record = 1641 dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL; 1642 1643 if (record) { 1644 record->call.type = CALL_TRANSFER_MAP; 1645 1646 dd_before_draw(dctx, record); 1647 } 1648 void *ptr = pipe->buffer_map(pipe, resource, level, usage, box, transfer); 1649 if (record) { 1650 record->call.info.transfer_map.transfer_ptr = *transfer; 1651 record->call.info.transfer_map.ptr = ptr; 1652 if (*transfer) { 1653 record->call.info.transfer_map.transfer = **transfer; 1654 record->call.info.transfer_map.transfer.resource = NULL; 1655 pipe_resource_reference(&record->call.info.transfer_map.transfer.resource, 1656 (*transfer)->resource); 1657 } else { 1658 memset(&record->call.info.transfer_map.transfer, 0, sizeof(struct pipe_transfer)); 1659 } 1660 1661 dd_after_draw(dctx, record); 1662 } 1663 return ptr; 1664} 1665 1666static void * 1667dd_context_texture_map(struct pipe_context *_pipe, 1668 struct pipe_resource *resource, unsigned level, 1669 unsigned usage, const struct pipe_box *box, 1670 struct pipe_transfer **transfer) 1671{ 1672 struct dd_context *dctx = dd_context(_pipe); 1673 struct pipe_context *pipe = dctx->pipe; 1674 struct dd_draw_record *record = 1675 dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL; 1676 1677 if (record) { 1678 record->call.type = CALL_TRANSFER_MAP; 1679 1680 dd_before_draw(dctx, record); 1681 } 1682 void *ptr = pipe->texture_map(pipe, resource, level, usage, box, transfer); 1683 if (record) { 1684 record->call.info.transfer_map.transfer_ptr = *transfer; 1685 record->call.info.transfer_map.ptr = ptr; 1686 if (*transfer) { 1687 record->call.info.transfer_map.transfer = **transfer; 1688 record->call.info.transfer_map.transfer.resource = NULL; 1689 pipe_resource_reference(&record->call.info.transfer_map.transfer.resource, 1690 (*transfer)->resource); 1691 } else { 1692 memset(&record->call.info.transfer_map.transfer, 0, sizeof(struct pipe_transfer)); 1693 } 1694 1695 dd_after_draw(dctx, record); 1696 } 1697 return ptr; 1698} 1699 1700static void 1701dd_context_transfer_flush_region(struct pipe_context *_pipe, 1702 struct pipe_transfer *transfer, 1703 const struct pipe_box *box) 1704{ 1705 struct dd_context *dctx = dd_context(_pipe); 1706 struct pipe_context *pipe = dctx->pipe; 1707 struct dd_draw_record *record = 1708 dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL; 1709 1710 if (record) { 1711 record->call.type = CALL_TRANSFER_FLUSH_REGION; 1712 record->call.info.transfer_flush_region.transfer_ptr = transfer; 1713 record->call.info.transfer_flush_region.box = *box; 1714 record->call.info.transfer_flush_region.transfer = *transfer; 1715 record->call.info.transfer_flush_region.transfer.resource = NULL; 1716 pipe_resource_reference( 1717 &record->call.info.transfer_flush_region.transfer.resource, 1718 transfer->resource); 1719 1720 dd_before_draw(dctx, record); 1721 } 1722 pipe->transfer_flush_region(pipe, transfer, box); 1723 if (record) 1724 dd_after_draw(dctx, record); 1725} 1726 1727static void 1728dd_context_buffer_unmap(struct pipe_context *_pipe, 1729 struct pipe_transfer *transfer) 1730{ 1731 struct dd_context *dctx = dd_context(_pipe); 1732 struct pipe_context *pipe = dctx->pipe; 1733 struct dd_draw_record *record = 1734 dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL; 1735 1736 if (record) { 1737 record->call.type = CALL_TRANSFER_UNMAP; 1738 record->call.info.transfer_unmap.transfer_ptr = transfer; 1739 record->call.info.transfer_unmap.transfer = *transfer; 1740 record->call.info.transfer_unmap.transfer.resource = NULL; 1741 pipe_resource_reference( 1742 &record->call.info.transfer_unmap.transfer.resource, 1743 transfer->resource); 1744 1745 dd_before_draw(dctx, record); 1746 } 1747 pipe->buffer_unmap(pipe, transfer); 1748 if (record) 1749 dd_after_draw(dctx, record); 1750} 1751 1752static void 1753dd_context_texture_unmap(struct pipe_context *_pipe, 1754 struct pipe_transfer *transfer) 1755{ 1756 struct dd_context *dctx = dd_context(_pipe); 1757 struct pipe_context *pipe = dctx->pipe; 1758 struct dd_draw_record *record = 1759 dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL; 1760 1761 if (record) { 1762 record->call.type = CALL_TRANSFER_UNMAP; 1763 record->call.info.transfer_unmap.transfer_ptr = transfer; 1764 record->call.info.transfer_unmap.transfer = *transfer; 1765 record->call.info.transfer_unmap.transfer.resource = NULL; 1766 pipe_resource_reference( 1767 &record->call.info.transfer_unmap.transfer.resource, 1768 transfer->resource); 1769 1770 dd_before_draw(dctx, record); 1771 } 1772 pipe->texture_unmap(pipe, transfer); 1773 if (record) 1774 dd_after_draw(dctx, record); 1775} 1776 1777static void 1778dd_context_buffer_subdata(struct pipe_context *_pipe, 1779 struct pipe_resource *resource, 1780 unsigned usage, unsigned offset, 1781 unsigned size, const void *data) 1782{ 1783 struct dd_context *dctx = dd_context(_pipe); 1784 struct pipe_context *pipe = dctx->pipe; 1785 struct dd_draw_record *record = 1786 dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL; 1787 1788 if (record) { 1789 record->call.type = CALL_BUFFER_SUBDATA; 1790 record->call.info.buffer_subdata.resource = NULL; 1791 pipe_resource_reference(&record->call.info.buffer_subdata.resource, resource); 1792 record->call.info.buffer_subdata.usage = usage; 1793 record->call.info.buffer_subdata.offset = offset; 1794 record->call.info.buffer_subdata.size = size; 1795 record->call.info.buffer_subdata.data = data; 1796 1797 dd_before_draw(dctx, record); 1798 } 1799 pipe->buffer_subdata(pipe, resource, usage, offset, size, data); 1800 if (record) 1801 dd_after_draw(dctx, record); 1802} 1803 1804static void 1805dd_context_texture_subdata(struct pipe_context *_pipe, 1806 struct pipe_resource *resource, 1807 unsigned level, unsigned usage, 1808 const struct pipe_box *box, 1809 const void *data, unsigned stride, 1810 unsigned layer_stride) 1811{ 1812 struct dd_context *dctx = dd_context(_pipe); 1813 struct pipe_context *pipe = dctx->pipe; 1814 struct dd_draw_record *record = 1815 dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL; 1816 1817 if (record) { 1818 record->call.type = CALL_TEXTURE_SUBDATA; 1819 record->call.info.texture_subdata.resource = NULL; 1820 pipe_resource_reference(&record->call.info.texture_subdata.resource, resource); 1821 record->call.info.texture_subdata.level = level; 1822 record->call.info.texture_subdata.usage = usage; 1823 record->call.info.texture_subdata.box = *box; 1824 record->call.info.texture_subdata.data = data; 1825 record->call.info.texture_subdata.stride = stride; 1826 record->call.info.texture_subdata.layer_stride = layer_stride; 1827 1828 dd_before_draw(dctx, record); 1829 } 1830 pipe->texture_subdata(pipe, resource, level, usage, box, data, 1831 stride, layer_stride); 1832 if (record) 1833 dd_after_draw(dctx, record); 1834} 1835 1836void 1837dd_init_draw_functions(struct dd_context *dctx) 1838{ 1839 CTX_INIT(flush); 1840 CTX_INIT(draw_vbo); 1841 CTX_INIT(launch_grid); 1842 CTX_INIT(resource_copy_region); 1843 CTX_INIT(blit); 1844 CTX_INIT(clear); 1845 CTX_INIT(clear_render_target); 1846 CTX_INIT(clear_depth_stencil); 1847 CTX_INIT(clear_buffer); 1848 CTX_INIT(clear_texture); 1849 CTX_INIT(flush_resource); 1850 CTX_INIT(generate_mipmap); 1851 CTX_INIT(get_query_result_resource); 1852 CTX_INIT(buffer_map); 1853 CTX_INIT(texture_map); 1854 CTX_INIT(transfer_flush_region); 1855 CTX_INIT(buffer_unmap); 1856 CTX_INIT(texture_unmap); 1857 CTX_INIT(buffer_subdata); 1858 CTX_INIT(texture_subdata); 1859 CTX_INIT(draw_vertex_state); 1860} 1861