ddebug: separate draw call dumping logic
[mesa.git] / src / gallium / drivers / ddebug / dd_draw.c
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/u_format.h"
32 #include "tgsi/tgsi_scan.h"
33
34
35 enum call_type
36 {
37 CALL_DRAW_VBO,
38 CALL_LAUNCH_GRID,
39 CALL_RESOURCE_COPY_REGION,
40 CALL_BLIT,
41 CALL_FLUSH_RESOURCE,
42 CALL_CLEAR,
43 CALL_CLEAR_BUFFER,
44 CALL_CLEAR_RENDER_TARGET,
45 CALL_CLEAR_DEPTH_STENCIL,
46 CALL_GENERATE_MIPMAP,
47 };
48
49 struct call_resource_copy_region
50 {
51 struct pipe_resource *dst;
52 unsigned dst_level;
53 unsigned dstx, dsty, dstz;
54 struct pipe_resource *src;
55 unsigned src_level;
56 const struct pipe_box *src_box;
57 };
58
59 struct call_clear
60 {
61 unsigned buffers;
62 const union pipe_color_union *color;
63 double depth;
64 unsigned stencil;
65 };
66
67 struct call_clear_buffer
68 {
69 struct pipe_resource *res;
70 unsigned offset;
71 unsigned size;
72 const void *clear_value;
73 int clear_value_size;
74 };
75
76 struct call_generate_mipmap {
77 struct pipe_resource *res;
78 enum pipe_format format;
79 unsigned base_level;
80 unsigned last_level;
81 unsigned first_layer;
82 unsigned last_layer;
83 };
84
85 struct dd_call
86 {
87 enum call_type type;
88
89 union {
90 struct pipe_draw_info draw_vbo;
91 struct pipe_grid_info launch_grid;
92 struct call_resource_copy_region resource_copy_region;
93 struct pipe_blit_info blit;
94 struct pipe_resource *flush_resource;
95 struct call_clear clear;
96 struct call_clear_buffer clear_buffer;
97 struct call_generate_mipmap generate_mipmap;
98 } info;
99 };
100
101 static FILE *
102 dd_get_file_stream(struct dd_screen *dscreen, unsigned apitrace_call_number)
103 {
104 struct pipe_screen *screen = dscreen->screen;
105 FILE *f = dd_get_debug_file(dscreen->verbose);
106 if (!f)
107 return NULL;
108
109 fprintf(f, "Driver vendor: %s\n", screen->get_vendor(screen));
110 fprintf(f, "Device vendor: %s\n", screen->get_device_vendor(screen));
111 fprintf(f, "Device name: %s\n\n", screen->get_name(screen));
112
113 if (apitrace_call_number)
114 fprintf(f, "Last apitrace call: %u\n\n",
115 apitrace_call_number);
116 return f;
117 }
118
119 static void
120 dd_dump_dmesg(FILE *f)
121 {
122 char line[2000];
123 FILE *p = popen("dmesg | tail -n60", "r");
124
125 if (!p)
126 return;
127
128 fprintf(f, "\nLast 60 lines of dmesg:\n\n");
129 while (fgets(line, sizeof(line), p))
130 fputs(line, f);
131
132 fclose(p);
133 }
134
135 static void
136 dd_close_file_stream(FILE *f)
137 {
138 fclose(f);
139 }
140
141 static unsigned
142 dd_num_active_viewports(struct dd_draw_state *dstate)
143 {
144 struct tgsi_shader_info info;
145 const struct tgsi_token *tokens;
146
147 if (dstate->shaders[PIPE_SHADER_GEOMETRY])
148 tokens = dstate->shaders[PIPE_SHADER_GEOMETRY]->state.shader.tokens;
149 else if (dstate->shaders[PIPE_SHADER_TESS_EVAL])
150 tokens = dstate->shaders[PIPE_SHADER_TESS_EVAL]->state.shader.tokens;
151 else if (dstate->shaders[PIPE_SHADER_VERTEX])
152 tokens = dstate->shaders[PIPE_SHADER_VERTEX]->state.shader.tokens;
153 else
154 return 1;
155
156 tgsi_scan_shader(tokens, &info);
157 return info.writes_viewport_index ? PIPE_MAX_VIEWPORTS : 1;
158 }
159
160 #define COLOR_RESET "\033[0m"
161 #define COLOR_SHADER "\033[1;32m"
162 #define COLOR_STATE "\033[1;33m"
163
164 #define DUMP(name, var) do { \
165 fprintf(f, COLOR_STATE #name ": " COLOR_RESET); \
166 util_dump_##name(f, var); \
167 fprintf(f, "\n"); \
168 } while(0)
169
170 #define DUMP_I(name, var, i) do { \
171 fprintf(f, COLOR_STATE #name " %i: " COLOR_RESET, i); \
172 util_dump_##name(f, var); \
173 fprintf(f, "\n"); \
174 } while(0)
175
176 #define DUMP_M(name, var, member) do { \
177 fprintf(f, " " #member ": "); \
178 util_dump_##name(f, (var)->member); \
179 fprintf(f, "\n"); \
180 } while(0)
181
182 #define DUMP_M_ADDR(name, var, member) do { \
183 fprintf(f, " " #member ": "); \
184 util_dump_##name(f, &(var)->member); \
185 fprintf(f, "\n"); \
186 } while(0)
187
188 static void
189 print_named_value(FILE *f, const char *name, int value)
190 {
191 fprintf(f, COLOR_STATE "%s" COLOR_RESET " = %i\n", name, value);
192 }
193
194 static void
195 print_named_xvalue(FILE *f, const char *name, int value)
196 {
197 fprintf(f, COLOR_STATE "%s" COLOR_RESET " = 0x%08x\n", name, value);
198 }
199
200 static void
201 util_dump_uint(FILE *f, unsigned i)
202 {
203 fprintf(f, "%u", i);
204 }
205
206 static void
207 util_dump_hex(FILE *f, unsigned i)
208 {
209 fprintf(f, "0x%x", i);
210 }
211
212 static void
213 util_dump_double(FILE *f, double d)
214 {
215 fprintf(f, "%f", d);
216 }
217
218 static void
219 util_dump_format(FILE *f, enum pipe_format format)
220 {
221 fprintf(f, "%s", util_format_name(format));
222 }
223
224 static void
225 util_dump_color_union(FILE *f, const union pipe_color_union *color)
226 {
227 fprintf(f, "{f = {%f, %f, %f, %f}, ui = {%u, %u, %u, %u}",
228 color->f[0], color->f[1], color->f[2], color->f[3],
229 color->ui[0], color->ui[1], color->ui[2], color->ui[3]);
230 }
231
232 static void
233 util_dump_query(FILE *f, struct dd_query *query)
234 {
235 if (query->type >= PIPE_QUERY_DRIVER_SPECIFIC)
236 fprintf(f, "PIPE_QUERY_DRIVER_SPECIFIC + %i",
237 query->type - PIPE_QUERY_DRIVER_SPECIFIC);
238 else
239 fprintf(f, "%s", util_dump_query_type(query->type, false));
240 }
241
242 static void
243 dd_dump_render_condition(struct dd_draw_state *dstate, FILE *f)
244 {
245 if (dstate->render_cond.query) {
246 fprintf(f, "render condition:\n");
247 DUMP_M(query, &dstate->render_cond, query);
248 DUMP_M(uint, &dstate->render_cond, condition);
249 DUMP_M(uint, &dstate->render_cond, mode);
250 fprintf(f, "\n");
251 }
252 }
253
254 static void
255 dd_dump_draw_vbo(struct dd_draw_state *dstate, struct pipe_draw_info *info, FILE *f)
256 {
257 int sh, i;
258 const char *shader_str[PIPE_SHADER_TYPES];
259
260 shader_str[PIPE_SHADER_VERTEX] = "VERTEX";
261 shader_str[PIPE_SHADER_TESS_CTRL] = "TESS_CTRL";
262 shader_str[PIPE_SHADER_TESS_EVAL] = "TESS_EVAL";
263 shader_str[PIPE_SHADER_GEOMETRY] = "GEOMETRY";
264 shader_str[PIPE_SHADER_FRAGMENT] = "FRAGMENT";
265 shader_str[PIPE_SHADER_COMPUTE] = "COMPUTE";
266
267 DUMP(draw_info, info);
268 if (info->indexed) {
269 DUMP(index_buffer, &dstate->index_buffer);
270 if (dstate->index_buffer.buffer)
271 DUMP_M(resource, &dstate->index_buffer, buffer);
272 }
273 if (info->count_from_stream_output)
274 DUMP_M(stream_output_target, info,
275 count_from_stream_output);
276 if (info->indirect)
277 DUMP_M(resource, info, indirect);
278 fprintf(f, "\n");
279
280 /* TODO: dump active queries */
281
282 dd_dump_render_condition(dstate, f);
283
284 for (i = 0; i < PIPE_MAX_ATTRIBS; i++)
285 if (dstate->vertex_buffers[i].buffer ||
286 dstate->vertex_buffers[i].user_buffer) {
287 DUMP_I(vertex_buffer, &dstate->vertex_buffers[i], i);
288 if (dstate->vertex_buffers[i].buffer)
289 DUMP_M(resource, &dstate->vertex_buffers[i], buffer);
290 }
291
292 if (dstate->velems) {
293 print_named_value(f, "num vertex elements",
294 dstate->velems->state.velems.count);
295 for (i = 0; i < dstate->velems->state.velems.count; i++) {
296 fprintf(f, " ");
297 DUMP_I(vertex_element, &dstate->velems->state.velems.velems[i], i);
298 }
299 }
300
301 print_named_value(f, "num stream output targets", dstate->num_so_targets);
302 for (i = 0; i < dstate->num_so_targets; i++)
303 if (dstate->so_targets[i]) {
304 DUMP_I(stream_output_target, dstate->so_targets[i], i);
305 DUMP_M(resource, dstate->so_targets[i], buffer);
306 fprintf(f, " offset = %i\n", dstate->so_offsets[i]);
307 }
308
309 fprintf(f, "\n");
310 for (sh = 0; sh < PIPE_SHADER_TYPES; sh++) {
311 if (sh == PIPE_SHADER_COMPUTE)
312 continue;
313
314 if (sh == PIPE_SHADER_TESS_CTRL &&
315 !dstate->shaders[PIPE_SHADER_TESS_CTRL] &&
316 dstate->shaders[PIPE_SHADER_TESS_EVAL])
317 fprintf(f, "tess_state: {default_outer_level = {%f, %f, %f, %f}, "
318 "default_inner_level = {%f, %f}}\n",
319 dstate->tess_default_levels[0],
320 dstate->tess_default_levels[1],
321 dstate->tess_default_levels[2],
322 dstate->tess_default_levels[3],
323 dstate->tess_default_levels[4],
324 dstate->tess_default_levels[5]);
325
326 if (sh == PIPE_SHADER_FRAGMENT)
327 if (dstate->rs) {
328 unsigned num_viewports = dd_num_active_viewports(dstate);
329
330 if (dstate->rs->state.rs.clip_plane_enable)
331 DUMP(clip_state, &dstate->clip_state);
332
333 for (i = 0; i < num_viewports; i++)
334 DUMP_I(viewport_state, &dstate->viewports[i], i);
335
336 if (dstate->rs->state.rs.scissor)
337 for (i = 0; i < num_viewports; i++)
338 DUMP_I(scissor_state, &dstate->scissors[i], i);
339
340 DUMP(rasterizer_state, &dstate->rs->state.rs);
341
342 if (dstate->rs->state.rs.poly_stipple_enable)
343 DUMP(poly_stipple, &dstate->polygon_stipple);
344 fprintf(f, "\n");
345 }
346
347 if (!dstate->shaders[sh])
348 continue;
349
350 fprintf(f, COLOR_SHADER "begin shader: %s" COLOR_RESET "\n", shader_str[sh]);
351 DUMP(shader_state, &dstate->shaders[sh]->state.shader);
352
353 for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++)
354 if (dstate->constant_buffers[sh][i].buffer ||
355 dstate->constant_buffers[sh][i].user_buffer) {
356 DUMP_I(constant_buffer, &dstate->constant_buffers[sh][i], i);
357 if (dstate->constant_buffers[sh][i].buffer)
358 DUMP_M(resource, &dstate->constant_buffers[sh][i], buffer);
359 }
360
361 for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
362 if (dstate->sampler_states[sh][i])
363 DUMP_I(sampler_state, &dstate->sampler_states[sh][i]->state.sampler, i);
364
365 for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
366 if (dstate->sampler_views[sh][i]) {
367 DUMP_I(sampler_view, dstate->sampler_views[sh][i], i);
368 DUMP_M(resource, dstate->sampler_views[sh][i], texture);
369 }
370
371 /* TODO: print shader images */
372 /* TODO: print shader buffers */
373
374 fprintf(f, COLOR_SHADER "end shader: %s" COLOR_RESET "\n\n", shader_str[sh]);
375 }
376
377 if (dstate->dsa)
378 DUMP(depth_stencil_alpha_state, &dstate->dsa->state.dsa);
379 DUMP(stencil_ref, &dstate->stencil_ref);
380
381 if (dstate->blend)
382 DUMP(blend_state, &dstate->blend->state.blend);
383 DUMP(blend_color, &dstate->blend_color);
384
385 print_named_value(f, "min_samples", dstate->min_samples);
386 print_named_xvalue(f, "sample_mask", dstate->sample_mask);
387 fprintf(f, "\n");
388
389 DUMP(framebuffer_state, &dstate->framebuffer_state);
390 for (i = 0; i < dstate->framebuffer_state.nr_cbufs; i++)
391 if (dstate->framebuffer_state.cbufs[i]) {
392 fprintf(f, " " COLOR_STATE "cbufs[%i]:" COLOR_RESET "\n ", i);
393 DUMP(surface, dstate->framebuffer_state.cbufs[i]);
394 fprintf(f, " ");
395 DUMP(resource, dstate->framebuffer_state.cbufs[i]->texture);
396 }
397 if (dstate->framebuffer_state.zsbuf) {
398 fprintf(f, " " COLOR_STATE "zsbuf:" COLOR_RESET "\n ");
399 DUMP(surface, dstate->framebuffer_state.zsbuf);
400 fprintf(f, " ");
401 DUMP(resource, dstate->framebuffer_state.zsbuf->texture);
402 }
403 fprintf(f, "\n");
404 }
405
406 static void
407 dd_dump_launch_grid(struct dd_draw_state *dstate, struct pipe_grid_info *info, FILE *f)
408 {
409 fprintf(f, "%s:\n", __func__+8);
410 /* TODO */
411 }
412
413 static void
414 dd_dump_resource_copy_region(struct dd_draw_state *dstate,
415 struct call_resource_copy_region *info,
416 FILE *f)
417 {
418 fprintf(f, "%s:\n", __func__+8);
419 DUMP_M(resource, info, dst);
420 DUMP_M(uint, info, dst_level);
421 DUMP_M(uint, info, dstx);
422 DUMP_M(uint, info, dsty);
423 DUMP_M(uint, info, dstz);
424 DUMP_M(resource, info, src);
425 DUMP_M(uint, info, src_level);
426 DUMP_M(box, info, src_box);
427 }
428
429 static void
430 dd_dump_blit(struct dd_draw_state *dstate, struct pipe_blit_info *info, FILE *f)
431 {
432 fprintf(f, "%s:\n", __func__+8);
433 DUMP_M(resource, info, dst.resource);
434 DUMP_M(uint, info, dst.level);
435 DUMP_M_ADDR(box, info, dst.box);
436 DUMP_M(format, info, dst.format);
437
438 DUMP_M(resource, info, src.resource);
439 DUMP_M(uint, info, src.level);
440 DUMP_M_ADDR(box, info, src.box);
441 DUMP_M(format, info, src.format);
442
443 DUMP_M(hex, info, mask);
444 DUMP_M(uint, info, filter);
445 DUMP_M(uint, info, scissor_enable);
446 DUMP_M_ADDR(scissor_state, info, scissor);
447 DUMP_M(uint, info, render_condition_enable);
448
449 if (info->render_condition_enable)
450 dd_dump_render_condition(dstate, f);
451 }
452
453 static void
454 dd_dump_generate_mipmap(struct dd_draw_state *dstate, FILE *f)
455 {
456 fprintf(f, "%s:\n", __func__+8);
457 /* TODO */
458 }
459
460 static void
461 dd_dump_flush_resource(struct dd_draw_state *dstate, struct pipe_resource *res,
462 FILE *f)
463 {
464 fprintf(f, "%s:\n", __func__+8);
465 DUMP(resource, res);
466 }
467
468 static void
469 dd_dump_clear(struct dd_draw_state *dstate, struct call_clear *info, FILE *f)
470 {
471 fprintf(f, "%s:\n", __func__+8);
472 DUMP_M(uint, info, buffers);
473 DUMP_M(color_union, info, color);
474 DUMP_M(double, info, depth);
475 DUMP_M(hex, info, stencil);
476 }
477
478 static void
479 dd_dump_clear_buffer(struct dd_draw_state *dstate, struct call_clear_buffer *info,
480 FILE *f)
481 {
482 int i;
483 const char *value = (const char*)info->clear_value;
484
485 fprintf(f, "%s:\n", __func__+8);
486 DUMP_M(resource, info, res);
487 DUMP_M(uint, info, offset);
488 DUMP_M(uint, info, size);
489 DUMP_M(uint, info, clear_value_size);
490
491 fprintf(f, " clear_value:");
492 for (i = 0; i < info->clear_value_size; i++)
493 fprintf(f, " %02x", value[i]);
494 fprintf(f, "\n");
495 }
496
497 static void
498 dd_dump_clear_render_target(struct dd_draw_state *dstate, FILE *f)
499 {
500 fprintf(f, "%s:\n", __func__+8);
501 /* TODO */
502 }
503
504 static void
505 dd_dump_clear_depth_stencil(struct dd_draw_state *dstate, FILE *f)
506 {
507 fprintf(f, "%s:\n", __func__+8);
508 /* TODO */
509 }
510
511 static void
512 dd_dump_driver_state(struct dd_context *dctx, FILE *f, unsigned flags)
513 {
514 if (dctx->pipe->dump_debug_state) {
515 fprintf(f,"\n\n**************************************************"
516 "***************************\n");
517 fprintf(f, "Driver-specific state:\n\n");
518 dctx->pipe->dump_debug_state(dctx->pipe, f, flags);
519 }
520 }
521
522 static void
523 dd_dump_call(FILE *f, struct dd_draw_state *state, struct dd_call *call)
524 {
525 switch (call->type) {
526 case CALL_DRAW_VBO:
527 dd_dump_draw_vbo(state, &call->info.draw_vbo, f);
528 break;
529 case CALL_LAUNCH_GRID:
530 dd_dump_launch_grid(state, &call->info.launch_grid, f);
531 break;
532 case CALL_RESOURCE_COPY_REGION:
533 dd_dump_resource_copy_region(state,
534 &call->info.resource_copy_region, f);
535 break;
536 case CALL_BLIT:
537 dd_dump_blit(state, &call->info.blit, f);
538 break;
539 case CALL_FLUSH_RESOURCE:
540 dd_dump_flush_resource(state, call->info.flush_resource, f);
541 break;
542 case CALL_CLEAR:
543 dd_dump_clear(state, &call->info.clear, f);
544 break;
545 case CALL_CLEAR_BUFFER:
546 dd_dump_clear_buffer(state, &call->info.clear_buffer, f);
547 break;
548 case CALL_CLEAR_RENDER_TARGET:
549 dd_dump_clear_render_target(state, f);
550 break;
551 case CALL_CLEAR_DEPTH_STENCIL:
552 dd_dump_clear_depth_stencil(state, f);
553 break;
554 case CALL_GENERATE_MIPMAP:
555 dd_dump_generate_mipmap(state, f);
556 break;
557 }
558 }
559
560 static void
561 dd_write_report(struct dd_context *dctx, struct dd_call *call, unsigned flags,
562 bool dump_dmesg)
563 {
564 FILE *f = dd_get_file_stream(dd_screen(dctx->base.screen),
565 dctx->draw_state.apitrace_call_number);
566
567 if (!f)
568 return;
569
570 dd_dump_call(f, &dctx->draw_state, call);
571 dd_dump_driver_state(dctx, f, flags);
572 if (dump_dmesg)
573 dd_dump_dmesg(f);
574 dd_close_file_stream(f);
575 }
576
577 static void
578 dd_kill_process(void)
579 {
580 sync();
581 fprintf(stderr, "dd: Aborting the process...\n");
582 fflush(stdout);
583 fflush(stderr);
584 exit(1);
585 }
586
587 static bool
588 dd_flush_and_check_hang(struct dd_context *dctx,
589 struct pipe_fence_handle **flush_fence,
590 unsigned flush_flags)
591 {
592 struct pipe_fence_handle *fence = NULL;
593 struct pipe_context *pipe = dctx->pipe;
594 struct pipe_screen *screen = pipe->screen;
595 uint64_t timeout_ms = dd_screen(dctx->base.screen)->timeout_ms;
596 bool idle;
597
598 assert(timeout_ms > 0);
599
600 pipe->flush(pipe, &fence, flush_flags);
601 if (flush_fence)
602 screen->fence_reference(screen, flush_fence, fence);
603 if (!fence)
604 return false;
605
606 idle = screen->fence_finish(screen, fence, timeout_ms * 1000000);
607 screen->fence_reference(screen, &fence, NULL);
608 if (!idle)
609 fprintf(stderr, "dd: GPU hang detected!\n");
610 return !idle;
611 }
612
613 static void
614 dd_flush_and_handle_hang(struct dd_context *dctx,
615 struct pipe_fence_handle **fence, unsigned flags,
616 const char *cause)
617 {
618 if (dd_flush_and_check_hang(dctx, fence, flags)) {
619 FILE *f = dd_get_file_stream(dd_screen(dctx->base.screen),
620 dctx->draw_state.apitrace_call_number);
621
622 if (f) {
623 fprintf(f, "dd: %s.\n", cause);
624 dd_dump_driver_state(dctx, f,
625 PIPE_DUMP_DEVICE_STATUS_REGISTERS |
626 PIPE_DUMP_CURRENT_STATES |
627 PIPE_DUMP_CURRENT_SHADERS |
628 PIPE_DUMP_LAST_COMMAND_BUFFER);
629 dd_dump_dmesg(f);
630 dd_close_file_stream(f);
631 }
632
633 /* Terminate the process to prevent future hangs. */
634 dd_kill_process();
635 }
636 }
637
638 static void
639 dd_context_flush(struct pipe_context *_pipe,
640 struct pipe_fence_handle **fence, unsigned flags)
641 {
642 struct dd_context *dctx = dd_context(_pipe);
643 struct pipe_context *pipe = dctx->pipe;
644
645 switch (dd_screen(dctx->base.screen)->mode) {
646 case DD_DETECT_HANGS:
647 dd_flush_and_handle_hang(dctx, fence, flags,
648 "GPU hang detected in pipe->flush()");
649 break;
650 case DD_DUMP_ALL_CALLS:
651 case DD_DUMP_APITRACE_CALL:
652 pipe->flush(pipe, fence, flags);
653 break;
654 default:
655 assert(0);
656 }
657 }
658
659 static void
660 dd_before_draw(struct dd_context *dctx)
661 {
662 struct dd_screen *dscreen = dd_screen(dctx->base.screen);
663
664 if (dscreen->mode == DD_DETECT_HANGS &&
665 !dscreen->no_flush &&
666 dctx->num_draw_calls >= dscreen->skip_count)
667 dd_flush_and_handle_hang(dctx, NULL, 0,
668 "GPU hang most likely caused by internal "
669 "driver commands");
670 }
671
672 static void
673 dd_after_draw(struct dd_context *dctx, struct dd_call *call)
674 {
675 struct dd_screen *dscreen = dd_screen(dctx->base.screen);
676 struct pipe_context *pipe = dctx->pipe;
677
678 if (dctx->num_draw_calls >= dscreen->skip_count) {
679 switch (dscreen->mode) {
680 case DD_DETECT_HANGS:
681 if (!dscreen->no_flush &&
682 dd_flush_and_check_hang(dctx, NULL, 0)) {
683 dd_write_report(dctx, call,
684 PIPE_DUMP_DEVICE_STATUS_REGISTERS |
685 PIPE_DUMP_CURRENT_STATES |
686 PIPE_DUMP_CURRENT_SHADERS |
687 PIPE_DUMP_LAST_COMMAND_BUFFER,
688 true);
689
690 /* Terminate the process to prevent future hangs. */
691 dd_kill_process();
692 }
693 break;
694 case DD_DUMP_ALL_CALLS:
695 if (!dscreen->no_flush)
696 pipe->flush(pipe, NULL, 0);
697 dd_write_report(dctx, call, 0, false);
698 break;
699 case DD_DUMP_APITRACE_CALL:
700 if (dscreen->apitrace_dump_call ==
701 dctx->draw_state.apitrace_call_number) {
702 dd_write_report(dctx, call, 0, false);
703 /* No need to continue. */
704 exit(0);
705 }
706 break;
707 default:
708 assert(0);
709 }
710 }
711
712 ++dctx->num_draw_calls;
713 if (dscreen->skip_count && dctx->num_draw_calls % 10000 == 0)
714 fprintf(stderr, "Gallium debugger reached %u draw calls.\n",
715 dctx->num_draw_calls);
716 }
717
718 static void
719 dd_context_draw_vbo(struct pipe_context *_pipe,
720 const struct pipe_draw_info *info)
721 {
722 struct dd_context *dctx = dd_context(_pipe);
723 struct pipe_context *pipe = dctx->pipe;
724 struct dd_call call;
725
726 call.type = CALL_DRAW_VBO;
727 call.info.draw_vbo = *info;
728
729 dd_before_draw(dctx);
730 pipe->draw_vbo(pipe, info);
731 dd_after_draw(dctx, &call);
732 }
733
734 static void
735 dd_context_launch_grid(struct pipe_context *_pipe,
736 const struct pipe_grid_info *info)
737 {
738 struct dd_context *dctx = dd_context(_pipe);
739 struct pipe_context *pipe = dctx->pipe;
740 struct dd_call call;
741
742 call.type = CALL_LAUNCH_GRID;
743 call.info.launch_grid = *info;
744
745 dd_before_draw(dctx);
746 pipe->launch_grid(pipe, info);
747 dd_after_draw(dctx, &call);
748 }
749
750 static void
751 dd_context_resource_copy_region(struct pipe_context *_pipe,
752 struct pipe_resource *dst, unsigned dst_level,
753 unsigned dstx, unsigned dsty, unsigned dstz,
754 struct pipe_resource *src, unsigned src_level,
755 const struct pipe_box *src_box)
756 {
757 struct dd_context *dctx = dd_context(_pipe);
758 struct pipe_context *pipe = dctx->pipe;
759 struct dd_call call;
760
761 call.type = CALL_RESOURCE_COPY_REGION;
762 call.info.resource_copy_region.dst = dst;
763 call.info.resource_copy_region.dst_level = dst_level;
764 call.info.resource_copy_region.dstx = dstx;
765 call.info.resource_copy_region.dsty = dsty;
766 call.info.resource_copy_region.dstz = dstz;
767 call.info.resource_copy_region.src = src;
768 call.info.resource_copy_region.src_level = src_level;
769 call.info.resource_copy_region.src_box = src_box;
770
771 dd_before_draw(dctx);
772 pipe->resource_copy_region(pipe,
773 dst, dst_level, dstx, dsty, dstz,
774 src, src_level, src_box);
775 dd_after_draw(dctx, &call);
776 }
777
778 static void
779 dd_context_blit(struct pipe_context *_pipe, const struct pipe_blit_info *info)
780 {
781 struct dd_context *dctx = dd_context(_pipe);
782 struct pipe_context *pipe = dctx->pipe;
783 struct dd_call call;
784
785 call.type = CALL_BLIT;
786 call.info.blit = *info;
787
788 dd_before_draw(dctx);
789 pipe->blit(pipe, info);
790 dd_after_draw(dctx, &call);
791 }
792
793 static boolean
794 dd_context_generate_mipmap(struct pipe_context *_pipe,
795 struct pipe_resource *res,
796 enum pipe_format format,
797 unsigned base_level,
798 unsigned last_level,
799 unsigned first_layer,
800 unsigned last_layer)
801 {
802 struct dd_context *dctx = dd_context(_pipe);
803 struct pipe_context *pipe = dctx->pipe;
804 struct dd_call call;
805 boolean result;
806
807 call.type = CALL_GENERATE_MIPMAP;
808 call.info.generate_mipmap.res = res;
809 call.info.generate_mipmap.format = format;
810 call.info.generate_mipmap.base_level = base_level;
811 call.info.generate_mipmap.last_level = last_level;
812 call.info.generate_mipmap.first_layer = first_layer;
813 call.info.generate_mipmap.last_layer = last_layer;
814
815 dd_before_draw(dctx);
816 result = pipe->generate_mipmap(pipe, res, format, base_level, last_level,
817 first_layer, last_layer);
818 dd_after_draw(dctx, &call);
819 return result;
820 }
821
822 static void
823 dd_context_flush_resource(struct pipe_context *_pipe,
824 struct pipe_resource *resource)
825 {
826 struct dd_context *dctx = dd_context(_pipe);
827 struct pipe_context *pipe = dctx->pipe;
828 struct dd_call call;
829
830 call.type = CALL_FLUSH_RESOURCE;
831 call.info.flush_resource = resource;
832
833 dd_before_draw(dctx);
834 pipe->flush_resource(pipe, resource);
835 dd_after_draw(dctx, &call);
836 }
837
838 static void
839 dd_context_clear(struct pipe_context *_pipe, unsigned buffers,
840 const union pipe_color_union *color, double depth,
841 unsigned stencil)
842 {
843 struct dd_context *dctx = dd_context(_pipe);
844 struct pipe_context *pipe = dctx->pipe;
845 struct dd_call call;
846
847 call.type = CALL_CLEAR;
848 call.info.clear.buffers = buffers;
849 call.info.clear.color = color;
850 call.info.clear.depth = depth;
851 call.info.clear.stencil = stencil;
852
853 dd_before_draw(dctx);
854 pipe->clear(pipe, buffers, color, depth, stencil);
855 dd_after_draw(dctx, &call);
856 }
857
858 static void
859 dd_context_clear_render_target(struct pipe_context *_pipe,
860 struct pipe_surface *dst,
861 const union pipe_color_union *color,
862 unsigned dstx, unsigned dsty,
863 unsigned width, unsigned height)
864 {
865 struct dd_context *dctx = dd_context(_pipe);
866 struct pipe_context *pipe = dctx->pipe;
867 struct dd_call call;
868
869 call.type = CALL_CLEAR_RENDER_TARGET;
870
871 dd_before_draw(dctx);
872 pipe->clear_render_target(pipe, dst, color, dstx, dsty, width, height);
873 dd_after_draw(dctx, &call);
874 }
875
876 static void
877 dd_context_clear_depth_stencil(struct pipe_context *_pipe,
878 struct pipe_surface *dst, unsigned clear_flags,
879 double depth, unsigned stencil, unsigned dstx,
880 unsigned dsty, unsigned width, unsigned height)
881 {
882 struct dd_context *dctx = dd_context(_pipe);
883 struct pipe_context *pipe = dctx->pipe;
884 struct dd_call call;
885
886 call.type = CALL_CLEAR_DEPTH_STENCIL;
887
888 dd_before_draw(dctx);
889 pipe->clear_depth_stencil(pipe, dst, clear_flags, depth, stencil,
890 dstx, dsty, width, height);
891 dd_after_draw(dctx, &call);
892 }
893
894 static void
895 dd_context_clear_buffer(struct pipe_context *_pipe, struct pipe_resource *res,
896 unsigned offset, unsigned size,
897 const void *clear_value, int clear_value_size)
898 {
899 struct dd_context *dctx = dd_context(_pipe);
900 struct pipe_context *pipe = dctx->pipe;
901 struct dd_call call;
902
903 call.type = CALL_CLEAR_BUFFER;
904 call.info.clear_buffer.res = res;
905 call.info.clear_buffer.offset = offset;
906 call.info.clear_buffer.size = size;
907 call.info.clear_buffer.clear_value = clear_value;
908 call.info.clear_buffer.clear_value_size = clear_value_size;
909
910 dd_before_draw(dctx);
911 pipe->clear_buffer(pipe, res, offset, size, clear_value, clear_value_size);
912 dd_after_draw(dctx, &call);
913 }
914
915 void
916 dd_init_draw_functions(struct dd_context *dctx)
917 {
918 CTX_INIT(flush);
919 CTX_INIT(draw_vbo);
920 CTX_INIT(launch_grid);
921 CTX_INIT(resource_copy_region);
922 CTX_INIT(blit);
923 CTX_INIT(clear);
924 CTX_INIT(clear_render_target);
925 CTX_INIT(clear_depth_stencil);
926 CTX_INIT(clear_buffer);
927 CTX_INIT(flush_resource);
928 CTX_INIT(generate_mipmap);
929 }