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