util: use standard name for snprintf()
[mesa.git] / src / gallium / auxiliary / driver_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 "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
43 void
44 dd_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, getpid(),
60 p_atomic_inc_return(&index) - 1);
61
62 if (verbose)
63 fprintf(stderr, "dd: dumping to file %s\n", buf);
64 }
65
66 FILE *
67 dd_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
82 void
83 dd_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
105 void
106 dd_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
119 FILE *
120 dd_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
132 static void
133 dd_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
150 static unsigned
151 dd_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) \
203 do { \
204 fprintf(f, COLOR_STATE "%s" COLOR_RESET " = ", name); \
205 util_dump_##type(f, value); \
206 fprintf(f, "\n"); \
207 } while (0)
208
209 static void
210 util_dump_uint(FILE *f, unsigned i)
211 {
212 fprintf(f, "%u", i);
213 }
214
215 static void
216 util_dump_int(FILE *f, int i)
217 {
218 fprintf(f, "%d", i);
219 }
220
221 static void
222 util_dump_hex(FILE *f, unsigned i)
223 {
224 fprintf(f, "0x%x", i);
225 }
226
227 static void
228 util_dump_double(FILE *f, double d)
229 {
230 fprintf(f, "%f", d);
231 }
232
233 static void
234 util_dump_format(FILE *f, enum pipe_format format)
235 {
236 fprintf(f, "%s", util_format_name(format));
237 }
238
239 static void
240 util_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
247 static void
248 dd_dump_render_condition(struct dd_draw_state *dstate, FILE *f)
249 {
250 if (dstate->render_cond.query) {
251 fprintf(f, "render condition:\n");
252 DUMP_M(query_type, &dstate->render_cond, query->type);
253 DUMP_M(uint, &dstate->render_cond, condition);
254 DUMP_M(uint, &dstate->render_cond, mode);
255 fprintf(f, "\n");
256 }
257 }
258
259 static void
260 dd_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
346 static void
347 dd_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
353 static void
354 dd_dump_draw_vbo(struct dd_draw_state *dstate, struct pipe_draw_info *info, FILE *f)
355 {
356 int sh, i;
357
358 DUMP(draw_info, info);
359 if (info->count_from_stream_output)
360 DUMP_M(stream_output_target, info,
361 count_from_stream_output);
362 if (info->indirect) {
363 DUMP_M(resource, info, indirect->buffer);
364 if (info->indirect->indirect_draw_count)
365 DUMP_M(resource, info, indirect->indirect_draw_count);
366 }
367
368 fprintf(f, "\n");
369
370 /* TODO: dump active queries */
371
372 dd_dump_render_condition(dstate, f);
373
374 for (i = 0; i < PIPE_MAX_ATTRIBS; i++)
375 if (dstate->vertex_buffers[i].buffer.resource) {
376 DUMP_I(vertex_buffer, &dstate->vertex_buffers[i], i);
377 if (!dstate->vertex_buffers[i].is_user_buffer)
378 DUMP_M(resource, &dstate->vertex_buffers[i], buffer.resource);
379 }
380
381 if (dstate->velems) {
382 PRINT_NAMED(uint, "num vertex elements",
383 dstate->velems->state.velems.count);
384 for (i = 0; i < dstate->velems->state.velems.count; i++) {
385 fprintf(f, " ");
386 DUMP_I(vertex_element, &dstate->velems->state.velems.velems[i], i);
387 }
388 }
389
390 PRINT_NAMED(uint, "num stream output targets", dstate->num_so_targets);
391 for (i = 0; i < dstate->num_so_targets; i++)
392 if (dstate->so_targets[i]) {
393 DUMP_I(stream_output_target, dstate->so_targets[i], i);
394 DUMP_M(resource, dstate->so_targets[i], buffer);
395 fprintf(f, " offset = %i\n", dstate->so_offsets[i]);
396 }
397
398 fprintf(f, "\n");
399 for (sh = 0; sh < PIPE_SHADER_TYPES; sh++) {
400 if (sh == PIPE_SHADER_COMPUTE)
401 continue;
402
403 dd_dump_shader(dstate, sh, f);
404 }
405
406 if (dstate->dsa)
407 DUMP(depth_stencil_alpha_state, &dstate->dsa->state.dsa);
408 DUMP(stencil_ref, &dstate->stencil_ref);
409
410 if (dstate->blend)
411 DUMP(blend_state, &dstate->blend->state.blend);
412 DUMP(blend_color, &dstate->blend_color);
413
414 PRINT_NAMED(uint, "min_samples", dstate->min_samples);
415 PRINT_NAMED(hex, "sample_mask", dstate->sample_mask);
416 fprintf(f, "\n");
417
418 DUMP(framebuffer_state, &dstate->framebuffer_state);
419 for (i = 0; i < dstate->framebuffer_state.nr_cbufs; i++)
420 if (dstate->framebuffer_state.cbufs[i]) {
421 fprintf(f, " " COLOR_STATE "cbufs[%i]:" COLOR_RESET "\n ", i);
422 DUMP(surface, dstate->framebuffer_state.cbufs[i]);
423 fprintf(f, " ");
424 DUMP(resource, dstate->framebuffer_state.cbufs[i]->texture);
425 }
426 if (dstate->framebuffer_state.zsbuf) {
427 fprintf(f, " " COLOR_STATE "zsbuf:" COLOR_RESET "\n ");
428 DUMP(surface, dstate->framebuffer_state.zsbuf);
429 fprintf(f, " ");
430 DUMP(resource, dstate->framebuffer_state.zsbuf->texture);
431 }
432 fprintf(f, "\n");
433 }
434
435 static void
436 dd_dump_launch_grid(struct dd_draw_state *dstate, struct pipe_grid_info *info, FILE *f)
437 {
438 fprintf(f, "%s:\n", __func__+8);
439 DUMP(grid_info, info);
440 fprintf(f, "\n");
441
442 dd_dump_shader(dstate, PIPE_SHADER_COMPUTE, f);
443 fprintf(f, "\n");
444 }
445
446 static void
447 dd_dump_resource_copy_region(struct dd_draw_state *dstate,
448 struct call_resource_copy_region *info,
449 FILE *f)
450 {
451 fprintf(f, "%s:\n", __func__+8);
452 DUMP_M(resource, info, dst);
453 DUMP_M(uint, info, dst_level);
454 DUMP_M(uint, info, dstx);
455 DUMP_M(uint, info, dsty);
456 DUMP_M(uint, info, dstz);
457 DUMP_M(resource, info, src);
458 DUMP_M(uint, info, src_level);
459 DUMP_M_ADDR(box, info, src_box);
460 }
461
462 static void
463 dd_dump_blit(struct dd_draw_state *dstate, struct pipe_blit_info *info, FILE *f)
464 {
465 fprintf(f, "%s:\n", __func__+8);
466 DUMP_M(resource, info, dst.resource);
467 DUMP_M(uint, info, dst.level);
468 DUMP_M_ADDR(box, info, dst.box);
469 DUMP_M(format, info, dst.format);
470
471 DUMP_M(resource, info, src.resource);
472 DUMP_M(uint, info, src.level);
473 DUMP_M_ADDR(box, info, src.box);
474 DUMP_M(format, info, src.format);
475
476 DUMP_M(hex, info, mask);
477 DUMP_M(uint, info, filter);
478 DUMP_M(uint, info, scissor_enable);
479 DUMP_M_ADDR(scissor_state, info, scissor);
480 DUMP_M(uint, info, render_condition_enable);
481
482 if (info->render_condition_enable)
483 dd_dump_render_condition(dstate, f);
484 }
485
486 static void
487 dd_dump_generate_mipmap(struct dd_draw_state *dstate, FILE *f)
488 {
489 fprintf(f, "%s:\n", __func__+8);
490 /* TODO */
491 }
492
493 static void
494 dd_dump_get_query_result_resource(struct call_get_query_result_resource *info, FILE *f)
495 {
496 fprintf(f, "%s:\n", __func__ + 8);
497 DUMP_M(query_type, info, query_type);
498 DUMP_M(uint, info, wait);
499 DUMP_M(query_value_type, info, result_type);
500 DUMP_M(int, info, index);
501 DUMP_M(resource, info, resource);
502 DUMP_M(uint, info, offset);
503 }
504
505 static void
506 dd_dump_flush_resource(struct dd_draw_state *dstate, struct pipe_resource *res,
507 FILE *f)
508 {
509 fprintf(f, "%s:\n", __func__+8);
510 DUMP(resource, res);
511 }
512
513 static void
514 dd_dump_clear(struct dd_draw_state *dstate, struct call_clear *info, FILE *f)
515 {
516 fprintf(f, "%s:\n", __func__+8);
517 DUMP_M(uint, info, buffers);
518 DUMP_M_ADDR(color_union, info, color);
519 DUMP_M(double, info, depth);
520 DUMP_M(hex, info, stencil);
521 }
522
523 static void
524 dd_dump_clear_buffer(struct dd_draw_state *dstate, struct call_clear_buffer *info,
525 FILE *f)
526 {
527 int i;
528 const char *value = (const char*)info->clear_value;
529
530 fprintf(f, "%s:\n", __func__+8);
531 DUMP_M(resource, info, res);
532 DUMP_M(uint, info, offset);
533 DUMP_M(uint, info, size);
534 DUMP_M(uint, info, clear_value_size);
535
536 fprintf(f, " clear_value:");
537 for (i = 0; i < info->clear_value_size; i++)
538 fprintf(f, " %02x", value[i]);
539 fprintf(f, "\n");
540 }
541
542 static void
543 dd_dump_transfer_map(struct call_transfer_map *info, FILE *f)
544 {
545 fprintf(f, "%s:\n", __func__+8);
546 DUMP_M_ADDR(transfer, info, transfer);
547 DUMP_M(ptr, info, transfer_ptr);
548 DUMP_M(ptr, info, ptr);
549 }
550
551 static void
552 dd_dump_transfer_flush_region(struct call_transfer_flush_region *info, FILE *f)
553 {
554 fprintf(f, "%s:\n", __func__+8);
555 DUMP_M_ADDR(transfer, info, transfer);
556 DUMP_M(ptr, info, transfer_ptr);
557 DUMP_M_ADDR(box, info, box);
558 }
559
560 static void
561 dd_dump_transfer_unmap(struct call_transfer_unmap *info, FILE *f)
562 {
563 fprintf(f, "%s:\n", __func__+8);
564 DUMP_M_ADDR(transfer, info, transfer);
565 DUMP_M(ptr, info, transfer_ptr);
566 }
567
568 static void
569 dd_dump_buffer_subdata(struct call_buffer_subdata *info, FILE *f)
570 {
571 fprintf(f, "%s:\n", __func__+8);
572 DUMP_M(resource, info, resource);
573 DUMP_M(transfer_usage, info, usage);
574 DUMP_M(uint, info, offset);
575 DUMP_M(uint, info, size);
576 DUMP_M(ptr, info, data);
577 }
578
579 static void
580 dd_dump_texture_subdata(struct call_texture_subdata *info, FILE *f)
581 {
582 fprintf(f, "%s:\n", __func__+8);
583 DUMP_M(resource, info, resource);
584 DUMP_M(uint, info, level);
585 DUMP_M(transfer_usage, info, usage);
586 DUMP_M_ADDR(box, info, box);
587 DUMP_M(ptr, info, data);
588 DUMP_M(uint, info, stride);
589 DUMP_M(uint, info, layer_stride);
590 }
591
592 static void
593 dd_dump_clear_texture(struct dd_draw_state *dstate, FILE *f)
594 {
595 fprintf(f, "%s:\n", __func__+8);
596 /* TODO */
597 }
598
599 static void
600 dd_dump_clear_render_target(struct dd_draw_state *dstate, FILE *f)
601 {
602 fprintf(f, "%s:\n", __func__+8);
603 /* TODO */
604 }
605
606 static void
607 dd_dump_clear_depth_stencil(struct dd_draw_state *dstate, FILE *f)
608 {
609 fprintf(f, "%s:\n", __func__+8);
610 /* TODO */
611 }
612
613 static void
614 dd_dump_driver_state(struct dd_context *dctx, FILE *f, unsigned flags)
615 {
616 if (dctx->pipe->dump_debug_state) {
617 fprintf(f,"\n\n**************************************************"
618 "***************************\n");
619 fprintf(f, "Driver-specific state:\n\n");
620 dctx->pipe->dump_debug_state(dctx->pipe, f, flags);
621 }
622 }
623
624 static void
625 dd_dump_call(FILE *f, struct dd_draw_state *state, struct dd_call *call)
626 {
627 switch (call->type) {
628 case CALL_FLUSH:
629 dd_dump_flush(state, &call->info.flush, f);
630 break;
631 case CALL_DRAW_VBO:
632 dd_dump_draw_vbo(state, &call->info.draw_vbo.draw, f);
633 break;
634 case CALL_LAUNCH_GRID:
635 dd_dump_launch_grid(state, &call->info.launch_grid, f);
636 break;
637 case CALL_RESOURCE_COPY_REGION:
638 dd_dump_resource_copy_region(state,
639 &call->info.resource_copy_region, f);
640 break;
641 case CALL_BLIT:
642 dd_dump_blit(state, &call->info.blit, f);
643 break;
644 case CALL_FLUSH_RESOURCE:
645 dd_dump_flush_resource(state, call->info.flush_resource, f);
646 break;
647 case CALL_CLEAR:
648 dd_dump_clear(state, &call->info.clear, f);
649 break;
650 case CALL_CLEAR_BUFFER:
651 dd_dump_clear_buffer(state, &call->info.clear_buffer, f);
652 break;
653 case CALL_CLEAR_TEXTURE:
654 dd_dump_clear_texture(state, f);
655 break;
656 case CALL_CLEAR_RENDER_TARGET:
657 dd_dump_clear_render_target(state, f);
658 break;
659 case CALL_CLEAR_DEPTH_STENCIL:
660 dd_dump_clear_depth_stencil(state, f);
661 break;
662 case CALL_GENERATE_MIPMAP:
663 dd_dump_generate_mipmap(state, f);
664 break;
665 case CALL_GET_QUERY_RESULT_RESOURCE:
666 dd_dump_get_query_result_resource(&call->info.get_query_result_resource, f);
667 break;
668 case CALL_TRANSFER_MAP:
669 dd_dump_transfer_map(&call->info.transfer_map, f);
670 break;
671 case CALL_TRANSFER_FLUSH_REGION:
672 dd_dump_transfer_flush_region(&call->info.transfer_flush_region, f);
673 break;
674 case CALL_TRANSFER_UNMAP:
675 dd_dump_transfer_unmap(&call->info.transfer_unmap, f);
676 break;
677 case CALL_BUFFER_SUBDATA:
678 dd_dump_buffer_subdata(&call->info.buffer_subdata, f);
679 break;
680 case CALL_TEXTURE_SUBDATA:
681 dd_dump_texture_subdata(&call->info.texture_subdata, f);
682 break;
683 }
684 }
685
686 static void
687 dd_kill_process(void)
688 {
689 #ifdef PIPE_OS_UNIX
690 sync();
691 #endif
692 fprintf(stderr, "dd: Aborting the process...\n");
693 fflush(stdout);
694 fflush(stderr);
695 exit(1);
696 }
697
698 static void
699 dd_unreference_copy_of_call(struct dd_call *dst)
700 {
701 switch (dst->type) {
702 case CALL_FLUSH:
703 break;
704 case CALL_DRAW_VBO:
705 pipe_so_target_reference(&dst->info.draw_vbo.draw.count_from_stream_output, NULL);
706 pipe_resource_reference(&dst->info.draw_vbo.indirect.buffer, NULL);
707 pipe_resource_reference(&dst->info.draw_vbo.indirect.indirect_draw_count, NULL);
708 if (dst->info.draw_vbo.draw.index_size &&
709 !dst->info.draw_vbo.draw.has_user_indices)
710 pipe_resource_reference(&dst->info.draw_vbo.draw.index.resource, NULL);
711 else
712 dst->info.draw_vbo.draw.index.user = NULL;
713 break;
714 case CALL_LAUNCH_GRID:
715 pipe_resource_reference(&dst->info.launch_grid.indirect, NULL);
716 break;
717 case CALL_RESOURCE_COPY_REGION:
718 pipe_resource_reference(&dst->info.resource_copy_region.dst, NULL);
719 pipe_resource_reference(&dst->info.resource_copy_region.src, NULL);
720 break;
721 case CALL_BLIT:
722 pipe_resource_reference(&dst->info.blit.dst.resource, NULL);
723 pipe_resource_reference(&dst->info.blit.src.resource, NULL);
724 break;
725 case CALL_FLUSH_RESOURCE:
726 pipe_resource_reference(&dst->info.flush_resource, NULL);
727 break;
728 case CALL_CLEAR:
729 break;
730 case CALL_CLEAR_BUFFER:
731 pipe_resource_reference(&dst->info.clear_buffer.res, NULL);
732 break;
733 case CALL_CLEAR_TEXTURE:
734 break;
735 case CALL_CLEAR_RENDER_TARGET:
736 break;
737 case CALL_CLEAR_DEPTH_STENCIL:
738 break;
739 case CALL_GENERATE_MIPMAP:
740 pipe_resource_reference(&dst->info.generate_mipmap.res, NULL);
741 break;
742 case CALL_GET_QUERY_RESULT_RESOURCE:
743 pipe_resource_reference(&dst->info.get_query_result_resource.resource, NULL);
744 break;
745 case CALL_TRANSFER_MAP:
746 pipe_resource_reference(&dst->info.transfer_map.transfer.resource, NULL);
747 break;
748 case CALL_TRANSFER_FLUSH_REGION:
749 pipe_resource_reference(&dst->info.transfer_flush_region.transfer.resource, NULL);
750 break;
751 case CALL_TRANSFER_UNMAP:
752 pipe_resource_reference(&dst->info.transfer_unmap.transfer.resource, NULL);
753 break;
754 case CALL_BUFFER_SUBDATA:
755 pipe_resource_reference(&dst->info.buffer_subdata.resource, NULL);
756 break;
757 case CALL_TEXTURE_SUBDATA:
758 pipe_resource_reference(&dst->info.texture_subdata.resource, NULL);
759 break;
760 }
761 }
762
763 static void
764 dd_init_copy_of_draw_state(struct dd_draw_state_copy *state)
765 {
766 unsigned i,j;
767
768 /* Just clear pointers to gallium objects. Don't clear the whole structure,
769 * because it would kill performance with its size of 130 KB.
770 */
771 memset(state->base.vertex_buffers, 0,
772 sizeof(state->base.vertex_buffers));
773 memset(state->base.so_targets, 0,
774 sizeof(state->base.so_targets));
775 memset(state->base.constant_buffers, 0,
776 sizeof(state->base.constant_buffers));
777 memset(state->base.sampler_views, 0,
778 sizeof(state->base.sampler_views));
779 memset(state->base.shader_images, 0,
780 sizeof(state->base.shader_images));
781 memset(state->base.shader_buffers, 0,
782 sizeof(state->base.shader_buffers));
783 memset(&state->base.framebuffer_state, 0,
784 sizeof(state->base.framebuffer_state));
785
786 memset(state->shaders, 0, sizeof(state->shaders));
787
788 state->base.render_cond.query = &state->render_cond;
789
790 for (i = 0; i < PIPE_SHADER_TYPES; i++) {
791 state->base.shaders[i] = &state->shaders[i];
792 for (j = 0; j < PIPE_MAX_SAMPLERS; j++)
793 state->base.sampler_states[i][j] = &state->sampler_states[i][j];
794 }
795
796 state->base.velems = &state->velems;
797 state->base.rs = &state->rs;
798 state->base.dsa = &state->dsa;
799 state->base.blend = &state->blend;
800 }
801
802 static void
803 dd_unreference_copy_of_draw_state(struct dd_draw_state_copy *state)
804 {
805 struct dd_draw_state *dst = &state->base;
806 unsigned i,j;
807
808 for (i = 0; i < ARRAY_SIZE(dst->vertex_buffers); i++)
809 pipe_vertex_buffer_unreference(&dst->vertex_buffers[i]);
810 for (i = 0; i < ARRAY_SIZE(dst->so_targets); i++)
811 pipe_so_target_reference(&dst->so_targets[i], NULL);
812
813 for (i = 0; i < PIPE_SHADER_TYPES; i++) {
814 if (dst->shaders[i])
815 tgsi_free_tokens(dst->shaders[i]->state.shader.tokens);
816
817 for (j = 0; j < PIPE_MAX_CONSTANT_BUFFERS; j++)
818 pipe_resource_reference(&dst->constant_buffers[i][j].buffer, NULL);
819 for (j = 0; j < PIPE_MAX_SAMPLERS; j++)
820 pipe_sampler_view_reference(&dst->sampler_views[i][j], NULL);
821 for (j = 0; j < PIPE_MAX_SHADER_IMAGES; j++)
822 pipe_resource_reference(&dst->shader_images[i][j].resource, NULL);
823 for (j = 0; j < PIPE_MAX_SHADER_BUFFERS; j++)
824 pipe_resource_reference(&dst->shader_buffers[i][j].buffer, NULL);
825 }
826
827 util_unreference_framebuffer_state(&dst->framebuffer_state);
828 }
829
830 static void
831 dd_copy_draw_state(struct dd_draw_state *dst, struct dd_draw_state *src)
832 {
833 unsigned i,j;
834
835 if (src->render_cond.query) {
836 *dst->render_cond.query = *src->render_cond.query;
837 dst->render_cond.condition = src->render_cond.condition;
838 dst->render_cond.mode = src->render_cond.mode;
839 } else {
840 dst->render_cond.query = NULL;
841 }
842
843 for (i = 0; i < ARRAY_SIZE(src->vertex_buffers); i++) {
844 pipe_vertex_buffer_reference(&dst->vertex_buffers[i],
845 &src->vertex_buffers[i]);
846 }
847
848 dst->num_so_targets = src->num_so_targets;
849 for (i = 0; i < src->num_so_targets; i++)
850 pipe_so_target_reference(&dst->so_targets[i], src->so_targets[i]);
851 memcpy(dst->so_offsets, src->so_offsets, sizeof(src->so_offsets));
852
853 for (i = 0; i < PIPE_SHADER_TYPES; i++) {
854 if (!src->shaders[i]) {
855 dst->shaders[i] = NULL;
856 continue;
857 }
858
859 if (src->shaders[i]) {
860 dst->shaders[i]->state.shader = src->shaders[i]->state.shader;
861 if (src->shaders[i]->state.shader.tokens) {
862 dst->shaders[i]->state.shader.tokens =
863 tgsi_dup_tokens(src->shaders[i]->state.shader.tokens);
864 } else {
865 dst->shaders[i]->state.shader.ir.nir = NULL;
866 }
867 } else {
868 dst->shaders[i] = NULL;
869 }
870
871 for (j = 0; j < PIPE_MAX_CONSTANT_BUFFERS; j++) {
872 pipe_resource_reference(&dst->constant_buffers[i][j].buffer,
873 src->constant_buffers[i][j].buffer);
874 memcpy(&dst->constant_buffers[i][j], &src->constant_buffers[i][j],
875 sizeof(src->constant_buffers[i][j]));
876 }
877
878 for (j = 0; j < PIPE_MAX_SAMPLERS; j++) {
879 pipe_sampler_view_reference(&dst->sampler_views[i][j],
880 src->sampler_views[i][j]);
881 if (src->sampler_states[i][j])
882 dst->sampler_states[i][j]->state.sampler =
883 src->sampler_states[i][j]->state.sampler;
884 else
885 dst->sampler_states[i][j] = NULL;
886 }
887
888 for (j = 0; j < PIPE_MAX_SHADER_IMAGES; j++) {
889 pipe_resource_reference(&dst->shader_images[i][j].resource,
890 src->shader_images[i][j].resource);
891 memcpy(&dst->shader_images[i][j], &src->shader_images[i][j],
892 sizeof(src->shader_images[i][j]));
893 }
894
895 for (j = 0; j < PIPE_MAX_SHADER_BUFFERS; j++) {
896 pipe_resource_reference(&dst->shader_buffers[i][j].buffer,
897 src->shader_buffers[i][j].buffer);
898 memcpy(&dst->shader_buffers[i][j], &src->shader_buffers[i][j],
899 sizeof(src->shader_buffers[i][j]));
900 }
901 }
902
903 if (src->velems)
904 dst->velems->state.velems = src->velems->state.velems;
905 else
906 dst->velems = NULL;
907
908 if (src->rs)
909 dst->rs->state.rs = src->rs->state.rs;
910 else
911 dst->rs = NULL;
912
913 if (src->dsa)
914 dst->dsa->state.dsa = src->dsa->state.dsa;
915 else
916 dst->dsa = NULL;
917
918 if (src->blend)
919 dst->blend->state.blend = src->blend->state.blend;
920 else
921 dst->blend = NULL;
922
923 dst->blend_color = src->blend_color;
924 dst->stencil_ref = src->stencil_ref;
925 dst->sample_mask = src->sample_mask;
926 dst->min_samples = src->min_samples;
927 dst->clip_state = src->clip_state;
928 util_copy_framebuffer_state(&dst->framebuffer_state, &src->framebuffer_state);
929 memcpy(dst->scissors, src->scissors, sizeof(src->scissors));
930 memcpy(dst->viewports, src->viewports, sizeof(src->viewports));
931 memcpy(dst->tess_default_levels, src->tess_default_levels,
932 sizeof(src->tess_default_levels));
933 dst->apitrace_call_number = src->apitrace_call_number;
934 }
935
936 static void
937 dd_free_record(struct pipe_screen *screen, struct dd_draw_record *record)
938 {
939 u_log_page_destroy(record->log_page);
940 dd_unreference_copy_of_call(&record->call);
941 dd_unreference_copy_of_draw_state(&record->draw_state);
942 screen->fence_reference(screen, &record->prev_bottom_of_pipe, NULL);
943 screen->fence_reference(screen, &record->top_of_pipe, NULL);
944 screen->fence_reference(screen, &record->bottom_of_pipe, NULL);
945 util_queue_fence_destroy(&record->driver_finished);
946 FREE(record);
947 }
948
949 static void
950 dd_write_record(FILE *f, struct dd_draw_record *record)
951 {
952 PRINT_NAMED(ptr, "pipe", record->dctx->pipe);
953 PRINT_NAMED(ns, "time before (API call)", record->time_before);
954 PRINT_NAMED(ns, "time after (driver done)", record->time_after);
955 fprintf(f, "\n");
956
957 dd_dump_call(f, &record->draw_state.base, &record->call);
958
959 if (record->log_page) {
960 fprintf(f,"\n\n**************************************************"
961 "***************************\n");
962 fprintf(f, "Context Log:\n\n");
963 u_log_page_print(record->log_page, f);
964 }
965 }
966
967 static void
968 dd_maybe_dump_record(struct dd_screen *dscreen, struct dd_draw_record *record)
969 {
970 if (dscreen->dump_mode == DD_DUMP_ONLY_HANGS ||
971 (dscreen->dump_mode == DD_DUMP_APITRACE_CALL &&
972 dscreen->apitrace_dump_call != record->draw_state.base.apitrace_call_number))
973 return;
974
975 char name[512];
976 dd_get_debug_filename_and_mkdir(name, sizeof(name), dscreen->verbose);
977 FILE *f = fopen(name, "w");
978 if (!f) {
979 fprintf(stderr, "dd: failed to open %s\n", name);
980 return;
981 }
982
983 dd_write_header(f, dscreen->screen, record->draw_state.base.apitrace_call_number);
984 dd_write_record(f, record);
985
986 fclose(f);
987 }
988
989 static const char *
990 dd_fence_state(struct pipe_screen *screen, struct pipe_fence_handle *fence,
991 bool *not_reached)
992 {
993 if (!fence)
994 return "---";
995
996 bool ok = screen->fence_finish(screen, NULL, fence, 0);
997
998 if (not_reached && !ok)
999 *not_reached = true;
1000
1001 return ok ? "YES" : "NO ";
1002 }
1003
1004 static void
1005 dd_report_hang(struct dd_context *dctx)
1006 {
1007 struct dd_screen *dscreen = dd_screen(dctx->base.screen);
1008 struct pipe_screen *screen = dscreen->screen;
1009 bool encountered_hang = false;
1010 bool stop_output = false;
1011 unsigned num_later = 0;
1012
1013 fprintf(stderr, "GPU hang detected, collecting information...\n\n");
1014
1015 fprintf(stderr, "Draw # driver prev BOP TOP BOP dump file\n"
1016 "-------------------------------------------------------------\n");
1017
1018 list_for_each_entry(struct dd_draw_record, record, &dctx->records, list) {
1019 if (!encountered_hang &&
1020 screen->fence_finish(screen, NULL, record->bottom_of_pipe, 0)) {
1021 dd_maybe_dump_record(dscreen, record);
1022 continue;
1023 }
1024
1025 if (stop_output) {
1026 dd_maybe_dump_record(dscreen, record);
1027 num_later++;
1028 continue;
1029 }
1030
1031 bool driver = util_queue_fence_is_signalled(&record->driver_finished);
1032 bool top_not_reached = false;
1033 const char *prev_bop = dd_fence_state(screen, record->prev_bottom_of_pipe, NULL);
1034 const char *top = dd_fence_state(screen, record->top_of_pipe, &top_not_reached);
1035 const char *bop = dd_fence_state(screen, record->bottom_of_pipe, NULL);
1036
1037 fprintf(stderr, "%-9u %s %s %s %s ",
1038 record->draw_call, driver ? "YES" : "NO ", prev_bop, top, bop);
1039
1040 char name[512];
1041 dd_get_debug_filename_and_mkdir(name, sizeof(name), false);
1042
1043 FILE *f = fopen(name, "w");
1044 if (!f) {
1045 fprintf(stderr, "fopen failed\n");
1046 } else {
1047 fprintf(stderr, "%s\n", name);
1048
1049 dd_write_header(f, dscreen->screen, record->draw_state.base.apitrace_call_number);
1050 dd_write_record(f, record);
1051
1052 fclose(f);
1053 }
1054
1055 if (top_not_reached)
1056 stop_output = true;
1057 encountered_hang = true;
1058 }
1059
1060 if (num_later)
1061 fprintf(stderr, "... and %u additional draws.\n", num_later);
1062
1063 char name[512];
1064 dd_get_debug_filename_and_mkdir(name, sizeof(name), false);
1065 FILE *f = fopen(name, "w");
1066 if (!f) {
1067 fprintf(stderr, "fopen failed\n");
1068 } else {
1069 dd_write_header(f, dscreen->screen, 0);
1070 dd_dump_driver_state(dctx, f, PIPE_DUMP_DEVICE_STATUS_REGISTERS);
1071 dd_dump_dmesg(f);
1072 fclose(f);
1073 }
1074
1075 fprintf(stderr, "\nDone.\n");
1076 dd_kill_process();
1077 }
1078
1079 int
1080 dd_thread_main(void *input)
1081 {
1082 struct dd_context *dctx = (struct dd_context *)input;
1083 struct dd_screen *dscreen = dd_screen(dctx->base.screen);
1084 struct pipe_screen *screen = dscreen->screen;
1085
1086 const char *process_name = util_get_process_name();
1087 if (process_name) {
1088 char threadname[16];
1089 snprintf(threadname, sizeof(threadname), "%.*s:ddbg",
1090 (int)MIN2(strlen(process_name), sizeof(threadname) - 6),
1091 process_name);
1092 u_thread_setname(threadname);
1093 }
1094
1095 mtx_lock(&dctx->mutex);
1096
1097 for (;;) {
1098 struct list_head records;
1099 list_replace(&dctx->records, &records);
1100 list_inithead(&dctx->records);
1101 dctx->num_records = 0;
1102
1103 if (dctx->api_stalled)
1104 cnd_signal(&dctx->cond);
1105
1106 if (list_empty(&records)) {
1107 if (dctx->kill_thread)
1108 break;
1109
1110 cnd_wait(&dctx->cond, &dctx->mutex);
1111 continue;
1112 }
1113
1114 mtx_unlock(&dctx->mutex);
1115
1116 /* Wait for the youngest draw. This means hangs can take a bit longer
1117 * to detect, but it's more efficient this way. */
1118 struct dd_draw_record *youngest =
1119 list_last_entry(&records, struct dd_draw_record, list);
1120
1121 if (dscreen->timeout_ms > 0) {
1122 uint64_t abs_timeout = os_time_get_absolute_timeout(
1123 (uint64_t)dscreen->timeout_ms * 1000*1000);
1124
1125 if (!util_queue_fence_wait_timeout(&youngest->driver_finished, abs_timeout) ||
1126 !screen->fence_finish(screen, NULL, youngest->bottom_of_pipe,
1127 (uint64_t)dscreen->timeout_ms * 1000*1000)) {
1128 mtx_lock(&dctx->mutex);
1129 list_splice(&records, &dctx->records);
1130 dd_report_hang(dctx);
1131 /* we won't actually get here */
1132 mtx_unlock(&dctx->mutex);
1133 }
1134 } else {
1135 util_queue_fence_wait(&youngest->driver_finished);
1136 }
1137
1138 list_for_each_entry_safe(struct dd_draw_record, record, &records, list) {
1139 dd_maybe_dump_record(dscreen, record);
1140 list_del(&record->list);
1141 dd_free_record(screen, record);
1142 }
1143
1144 mtx_lock(&dctx->mutex);
1145 }
1146 mtx_unlock(&dctx->mutex);
1147 return 0;
1148 }
1149
1150 static struct dd_draw_record *
1151 dd_create_record(struct dd_context *dctx)
1152 {
1153 struct dd_draw_record *record;
1154
1155 record = MALLOC_STRUCT(dd_draw_record);
1156 if (!record)
1157 return NULL;
1158
1159 record->dctx = dctx;
1160 record->draw_call = dctx->num_draw_calls;
1161
1162 record->prev_bottom_of_pipe = NULL;
1163 record->top_of_pipe = NULL;
1164 record->bottom_of_pipe = NULL;
1165 record->log_page = NULL;
1166 util_queue_fence_init(&record->driver_finished);
1167 util_queue_fence_reset(&record->driver_finished);
1168
1169 dd_init_copy_of_draw_state(&record->draw_state);
1170 dd_copy_draw_state(&record->draw_state.base, &dctx->draw_state);
1171
1172 return record;
1173 }
1174
1175 static void
1176 dd_add_record(struct dd_context *dctx, struct dd_draw_record *record)
1177 {
1178 mtx_lock(&dctx->mutex);
1179 if (unlikely(dctx->num_records > 10000)) {
1180 dctx->api_stalled = true;
1181 /* Since this is only a heuristic to prevent the API thread from getting
1182 * too far ahead, we don't need a loop here. */
1183 cnd_wait(&dctx->cond, &dctx->mutex);
1184 dctx->api_stalled = false;
1185 }
1186
1187 if (list_empty(&dctx->records))
1188 cnd_signal(&dctx->cond);
1189
1190 list_addtail(&record->list, &dctx->records);
1191 dctx->num_records++;
1192 mtx_unlock(&dctx->mutex);
1193 }
1194
1195 static void
1196 dd_before_draw(struct dd_context *dctx, struct dd_draw_record *record)
1197 {
1198 struct dd_screen *dscreen = dd_screen(dctx->base.screen);
1199 struct pipe_context *pipe = dctx->pipe;
1200 struct pipe_screen *screen = dscreen->screen;
1201
1202 record->time_before = os_time_get_nano();
1203
1204 if (dscreen->timeout_ms > 0) {
1205 if (dscreen->flush_always && dctx->num_draw_calls >= dscreen->skip_count) {
1206 pipe->flush(pipe, &record->prev_bottom_of_pipe, 0);
1207 screen->fence_reference(screen, &record->top_of_pipe, record->prev_bottom_of_pipe);
1208 } else {
1209 pipe->flush(pipe, &record->prev_bottom_of_pipe,
1210 PIPE_FLUSH_DEFERRED | PIPE_FLUSH_BOTTOM_OF_PIPE);
1211 pipe->flush(pipe, &record->top_of_pipe,
1212 PIPE_FLUSH_DEFERRED | PIPE_FLUSH_TOP_OF_PIPE);
1213 }
1214 } else if (dscreen->flush_always && dctx->num_draw_calls >= dscreen->skip_count) {
1215 pipe->flush(pipe, NULL, 0);
1216 }
1217
1218 dd_add_record(dctx, record);
1219 }
1220
1221 static void
1222 dd_after_draw_async(void *data)
1223 {
1224 struct dd_draw_record *record = (struct dd_draw_record *)data;
1225 struct dd_context *dctx = record->dctx;
1226 struct dd_screen *dscreen = dd_screen(dctx->base.screen);
1227
1228 record->log_page = u_log_new_page(&dctx->log);
1229 record->time_after = os_time_get_nano();
1230
1231 util_queue_fence_signal(&record->driver_finished);
1232
1233 if (dscreen->dump_mode == DD_DUMP_APITRACE_CALL &&
1234 dscreen->apitrace_dump_call > dctx->draw_state.apitrace_call_number) {
1235 dd_thread_join(dctx);
1236 /* No need to continue. */
1237 exit(0);
1238 }
1239 }
1240
1241 static void
1242 dd_after_draw(struct dd_context *dctx, struct dd_draw_record *record)
1243 {
1244 struct dd_screen *dscreen = dd_screen(dctx->base.screen);
1245 struct pipe_context *pipe = dctx->pipe;
1246
1247 if (dscreen->timeout_ms > 0) {
1248 unsigned flush_flags;
1249 if (dscreen->flush_always && dctx->num_draw_calls >= dscreen->skip_count)
1250 flush_flags = 0;
1251 else
1252 flush_flags = PIPE_FLUSH_DEFERRED | PIPE_FLUSH_BOTTOM_OF_PIPE;
1253 pipe->flush(pipe, &record->bottom_of_pipe, flush_flags);
1254 }
1255
1256 if (pipe->callback) {
1257 pipe->callback(pipe, dd_after_draw_async, record, true);
1258 } else {
1259 dd_after_draw_async(record);
1260 }
1261
1262 ++dctx->num_draw_calls;
1263 if (dscreen->skip_count && dctx->num_draw_calls % 10000 == 0)
1264 fprintf(stderr, "Gallium debugger reached %u draw calls.\n",
1265 dctx->num_draw_calls);
1266 }
1267
1268 static void
1269 dd_context_flush(struct pipe_context *_pipe,
1270 struct pipe_fence_handle **fence, unsigned flags)
1271 {
1272 struct dd_context *dctx = dd_context(_pipe);
1273 struct pipe_context *pipe = dctx->pipe;
1274 struct pipe_screen *screen = pipe->screen;
1275 struct dd_draw_record *record = dd_create_record(dctx);
1276
1277 record->call.type = CALL_FLUSH;
1278 record->call.info.flush.flags = flags;
1279
1280 record->time_before = os_time_get_nano();
1281
1282 dd_add_record(dctx, record);
1283
1284 pipe->flush(pipe, &record->bottom_of_pipe, flags);
1285 if (fence)
1286 screen->fence_reference(screen, fence, record->bottom_of_pipe);
1287
1288 if (pipe->callback) {
1289 pipe->callback(pipe, dd_after_draw_async, record, true);
1290 } else {
1291 dd_after_draw_async(record);
1292 }
1293 }
1294
1295 static void
1296 dd_context_draw_vbo(struct pipe_context *_pipe,
1297 const struct pipe_draw_info *info)
1298 {
1299 struct dd_context *dctx = dd_context(_pipe);
1300 struct pipe_context *pipe = dctx->pipe;
1301 struct dd_draw_record *record = dd_create_record(dctx);
1302
1303 record->call.type = CALL_DRAW_VBO;
1304 record->call.info.draw_vbo.draw = *info;
1305 record->call.info.draw_vbo.draw.count_from_stream_output = NULL;
1306 pipe_so_target_reference(&record->call.info.draw_vbo.draw.count_from_stream_output,
1307 info->count_from_stream_output);
1308 if (info->index_size && !info->has_user_indices) {
1309 record->call.info.draw_vbo.draw.index.resource = NULL;
1310 pipe_resource_reference(&record->call.info.draw_vbo.draw.index.resource,
1311 info->index.resource);
1312 }
1313
1314 if (info->indirect) {
1315 record->call.info.draw_vbo.indirect = *info->indirect;
1316 record->call.info.draw_vbo.draw.indirect = &record->call.info.draw_vbo.indirect;
1317
1318 record->call.info.draw_vbo.indirect.buffer = NULL;
1319 pipe_resource_reference(&record->call.info.draw_vbo.indirect.buffer,
1320 info->indirect->buffer);
1321 record->call.info.draw_vbo.indirect.indirect_draw_count = NULL;
1322 pipe_resource_reference(&record->call.info.draw_vbo.indirect.indirect_draw_count,
1323 info->indirect->indirect_draw_count);
1324 } else {
1325 memset(&record->call.info.draw_vbo.indirect, 0, sizeof(*info->indirect));
1326 }
1327
1328 dd_before_draw(dctx, record);
1329 pipe->draw_vbo(pipe, info);
1330 dd_after_draw(dctx, record);
1331 }
1332
1333 static void
1334 dd_context_launch_grid(struct pipe_context *_pipe,
1335 const struct pipe_grid_info *info)
1336 {
1337 struct dd_context *dctx = dd_context(_pipe);
1338 struct pipe_context *pipe = dctx->pipe;
1339 struct dd_draw_record *record = dd_create_record(dctx);
1340
1341 record->call.type = CALL_LAUNCH_GRID;
1342 record->call.info.launch_grid = *info;
1343 record->call.info.launch_grid.indirect = NULL;
1344 pipe_resource_reference(&record->call.info.launch_grid.indirect, info->indirect);
1345
1346 dd_before_draw(dctx, record);
1347 pipe->launch_grid(pipe, info);
1348 dd_after_draw(dctx, record);
1349 }
1350
1351 static void
1352 dd_context_resource_copy_region(struct pipe_context *_pipe,
1353 struct pipe_resource *dst, unsigned dst_level,
1354 unsigned dstx, unsigned dsty, unsigned dstz,
1355 struct pipe_resource *src, unsigned src_level,
1356 const struct pipe_box *src_box)
1357 {
1358 struct dd_context *dctx = dd_context(_pipe);
1359 struct pipe_context *pipe = dctx->pipe;
1360 struct dd_draw_record *record = dd_create_record(dctx);
1361
1362 record->call.type = CALL_RESOURCE_COPY_REGION;
1363 record->call.info.resource_copy_region.dst = NULL;
1364 pipe_resource_reference(&record->call.info.resource_copy_region.dst, dst);
1365 record->call.info.resource_copy_region.dst_level = dst_level;
1366 record->call.info.resource_copy_region.dstx = dstx;
1367 record->call.info.resource_copy_region.dsty = dsty;
1368 record->call.info.resource_copy_region.dstz = dstz;
1369 record->call.info.resource_copy_region.src = NULL;
1370 pipe_resource_reference(&record->call.info.resource_copy_region.src, src);
1371 record->call.info.resource_copy_region.src_level = src_level;
1372 record->call.info.resource_copy_region.src_box = *src_box;
1373
1374 dd_before_draw(dctx, record);
1375 pipe->resource_copy_region(pipe,
1376 dst, dst_level, dstx, dsty, dstz,
1377 src, src_level, src_box);
1378 dd_after_draw(dctx, record);
1379 }
1380
1381 static void
1382 dd_context_blit(struct pipe_context *_pipe, const struct pipe_blit_info *info)
1383 {
1384 struct dd_context *dctx = dd_context(_pipe);
1385 struct pipe_context *pipe = dctx->pipe;
1386 struct dd_draw_record *record = dd_create_record(dctx);
1387
1388 record->call.type = CALL_BLIT;
1389 record->call.info.blit = *info;
1390 record->call.info.blit.dst.resource = NULL;
1391 pipe_resource_reference(&record->call.info.blit.dst.resource, info->dst.resource);
1392 record->call.info.blit.src.resource = NULL;
1393 pipe_resource_reference(&record->call.info.blit.src.resource, info->src.resource);
1394
1395 dd_before_draw(dctx, record);
1396 pipe->blit(pipe, info);
1397 dd_after_draw(dctx, record);
1398 }
1399
1400 static boolean
1401 dd_context_generate_mipmap(struct pipe_context *_pipe,
1402 struct pipe_resource *res,
1403 enum pipe_format format,
1404 unsigned base_level,
1405 unsigned last_level,
1406 unsigned first_layer,
1407 unsigned last_layer)
1408 {
1409 struct dd_context *dctx = dd_context(_pipe);
1410 struct pipe_context *pipe = dctx->pipe;
1411 struct dd_draw_record *record = dd_create_record(dctx);
1412 boolean result;
1413
1414 record->call.type = CALL_GENERATE_MIPMAP;
1415 record->call.info.generate_mipmap.res = NULL;
1416 pipe_resource_reference(&record->call.info.generate_mipmap.res, res);
1417 record->call.info.generate_mipmap.format = format;
1418 record->call.info.generate_mipmap.base_level = base_level;
1419 record->call.info.generate_mipmap.last_level = last_level;
1420 record->call.info.generate_mipmap.first_layer = first_layer;
1421 record->call.info.generate_mipmap.last_layer = last_layer;
1422
1423 dd_before_draw(dctx, record);
1424 result = pipe->generate_mipmap(pipe, res, format, base_level, last_level,
1425 first_layer, last_layer);
1426 dd_after_draw(dctx, record);
1427 return result;
1428 }
1429
1430 static void
1431 dd_context_get_query_result_resource(struct pipe_context *_pipe,
1432 struct pipe_query *query,
1433 boolean wait,
1434 enum pipe_query_value_type result_type,
1435 int index,
1436 struct pipe_resource *resource,
1437 unsigned offset)
1438 {
1439 struct dd_context *dctx = dd_context(_pipe);
1440 struct dd_query *dquery = dd_query(query);
1441 struct pipe_context *pipe = dctx->pipe;
1442 struct dd_draw_record *record = dd_create_record(dctx);
1443
1444 record->call.type = CALL_GET_QUERY_RESULT_RESOURCE;
1445 record->call.info.get_query_result_resource.query = query;
1446 record->call.info.get_query_result_resource.wait = wait;
1447 record->call.info.get_query_result_resource.result_type = result_type;
1448 record->call.info.get_query_result_resource.index = index;
1449 record->call.info.get_query_result_resource.resource = NULL;
1450 pipe_resource_reference(&record->call.info.get_query_result_resource.resource,
1451 resource);
1452 record->call.info.get_query_result_resource.offset = offset;
1453
1454 /* The query may be deleted by the time we need to print it. */
1455 record->call.info.get_query_result_resource.query_type = dquery->type;
1456
1457 dd_before_draw(dctx, record);
1458 pipe->get_query_result_resource(pipe, dquery->query, wait,
1459 result_type, index, resource, offset);
1460 dd_after_draw(dctx, record);
1461 }
1462
1463 static void
1464 dd_context_flush_resource(struct pipe_context *_pipe,
1465 struct pipe_resource *resource)
1466 {
1467 struct dd_context *dctx = dd_context(_pipe);
1468 struct pipe_context *pipe = dctx->pipe;
1469 struct dd_draw_record *record = dd_create_record(dctx);
1470
1471 record->call.type = CALL_FLUSH_RESOURCE;
1472 record->call.info.flush_resource = NULL;
1473 pipe_resource_reference(&record->call.info.flush_resource, resource);
1474
1475 dd_before_draw(dctx, record);
1476 pipe->flush_resource(pipe, resource);
1477 dd_after_draw(dctx, record);
1478 }
1479
1480 static void
1481 dd_context_clear(struct pipe_context *_pipe, unsigned buffers,
1482 const union pipe_color_union *color, double depth,
1483 unsigned stencil)
1484 {
1485 struct dd_context *dctx = dd_context(_pipe);
1486 struct pipe_context *pipe = dctx->pipe;
1487 struct dd_draw_record *record = dd_create_record(dctx);
1488
1489 record->call.type = CALL_CLEAR;
1490 record->call.info.clear.buffers = buffers;
1491 record->call.info.clear.color = *color;
1492 record->call.info.clear.depth = depth;
1493 record->call.info.clear.stencil = stencil;
1494
1495 dd_before_draw(dctx, record);
1496 pipe->clear(pipe, buffers, color, depth, stencil);
1497 dd_after_draw(dctx, record);
1498 }
1499
1500 static void
1501 dd_context_clear_render_target(struct pipe_context *_pipe,
1502 struct pipe_surface *dst,
1503 const union pipe_color_union *color,
1504 unsigned dstx, unsigned dsty,
1505 unsigned width, unsigned height,
1506 bool render_condition_enabled)
1507 {
1508 struct dd_context *dctx = dd_context(_pipe);
1509 struct pipe_context *pipe = dctx->pipe;
1510 struct dd_draw_record *record = dd_create_record(dctx);
1511
1512 record->call.type = CALL_CLEAR_RENDER_TARGET;
1513
1514 dd_before_draw(dctx, record);
1515 pipe->clear_render_target(pipe, dst, color, dstx, dsty, width, height,
1516 render_condition_enabled);
1517 dd_after_draw(dctx, record);
1518 }
1519
1520 static void
1521 dd_context_clear_depth_stencil(struct pipe_context *_pipe,
1522 struct pipe_surface *dst, unsigned clear_flags,
1523 double depth, unsigned stencil, unsigned dstx,
1524 unsigned dsty, unsigned width, unsigned height,
1525 bool render_condition_enabled)
1526 {
1527 struct dd_context *dctx = dd_context(_pipe);
1528 struct pipe_context *pipe = dctx->pipe;
1529 struct dd_draw_record *record = dd_create_record(dctx);
1530
1531 record->call.type = CALL_CLEAR_DEPTH_STENCIL;
1532
1533 dd_before_draw(dctx, record);
1534 pipe->clear_depth_stencil(pipe, dst, clear_flags, depth, stencil,
1535 dstx, dsty, width, height,
1536 render_condition_enabled);
1537 dd_after_draw(dctx, record);
1538 }
1539
1540 static void
1541 dd_context_clear_buffer(struct pipe_context *_pipe, struct pipe_resource *res,
1542 unsigned offset, unsigned size,
1543 const void *clear_value, int clear_value_size)
1544 {
1545 struct dd_context *dctx = dd_context(_pipe);
1546 struct pipe_context *pipe = dctx->pipe;
1547 struct dd_draw_record *record = dd_create_record(dctx);
1548
1549 record->call.type = CALL_CLEAR_BUFFER;
1550 record->call.info.clear_buffer.res = NULL;
1551 pipe_resource_reference(&record->call.info.clear_buffer.res, res);
1552 record->call.info.clear_buffer.offset = offset;
1553 record->call.info.clear_buffer.size = size;
1554 record->call.info.clear_buffer.clear_value = clear_value;
1555 record->call.info.clear_buffer.clear_value_size = clear_value_size;
1556
1557 dd_before_draw(dctx, record);
1558 pipe->clear_buffer(pipe, res, offset, size, clear_value, clear_value_size);
1559 dd_after_draw(dctx, record);
1560 }
1561
1562 static void
1563 dd_context_clear_texture(struct pipe_context *_pipe,
1564 struct pipe_resource *res,
1565 unsigned level,
1566 const struct pipe_box *box,
1567 const void *data)
1568 {
1569 struct dd_context *dctx = dd_context(_pipe);
1570 struct pipe_context *pipe = dctx->pipe;
1571 struct dd_draw_record *record = dd_create_record(dctx);
1572
1573 record->call.type = CALL_CLEAR_TEXTURE;
1574
1575 dd_before_draw(dctx, record);
1576 pipe->clear_texture(pipe, res, level, box, data);
1577 dd_after_draw(dctx, record);
1578 }
1579
1580 /********************************************************************
1581 * transfer
1582 */
1583
1584 static void *
1585 dd_context_transfer_map(struct pipe_context *_pipe,
1586 struct pipe_resource *resource, unsigned level,
1587 unsigned usage, const struct pipe_box *box,
1588 struct pipe_transfer **transfer)
1589 {
1590 struct dd_context *dctx = dd_context(_pipe);
1591 struct pipe_context *pipe = dctx->pipe;
1592 struct dd_draw_record *record =
1593 dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL;
1594
1595 if (record) {
1596 record->call.type = CALL_TRANSFER_MAP;
1597
1598 dd_before_draw(dctx, record);
1599 }
1600 void *ptr = pipe->transfer_map(pipe, resource, level, usage, box, transfer);
1601 if (record) {
1602 record->call.info.transfer_map.transfer_ptr = *transfer;
1603 record->call.info.transfer_map.ptr = ptr;
1604 if (*transfer) {
1605 record->call.info.transfer_map.transfer = **transfer;
1606 record->call.info.transfer_map.transfer.resource = NULL;
1607 pipe_resource_reference(&record->call.info.transfer_map.transfer.resource,
1608 (*transfer)->resource);
1609 } else {
1610 memset(&record->call.info.transfer_map.transfer, 0, sizeof(struct pipe_transfer));
1611 }
1612
1613 dd_after_draw(dctx, record);
1614 }
1615 return ptr;
1616 }
1617
1618 static void
1619 dd_context_transfer_flush_region(struct pipe_context *_pipe,
1620 struct pipe_transfer *transfer,
1621 const struct pipe_box *box)
1622 {
1623 struct dd_context *dctx = dd_context(_pipe);
1624 struct pipe_context *pipe = dctx->pipe;
1625 struct dd_draw_record *record =
1626 dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL;
1627
1628 if (record) {
1629 record->call.type = CALL_TRANSFER_FLUSH_REGION;
1630 record->call.info.transfer_flush_region.transfer_ptr = transfer;
1631 record->call.info.transfer_flush_region.box = *box;
1632 record->call.info.transfer_flush_region.transfer = *transfer;
1633 record->call.info.transfer_flush_region.transfer.resource = NULL;
1634 pipe_resource_reference(
1635 &record->call.info.transfer_flush_region.transfer.resource,
1636 transfer->resource);
1637
1638 dd_before_draw(dctx, record);
1639 }
1640 pipe->transfer_flush_region(pipe, transfer, box);
1641 if (record)
1642 dd_after_draw(dctx, record);
1643 }
1644
1645 static void
1646 dd_context_transfer_unmap(struct pipe_context *_pipe,
1647 struct pipe_transfer *transfer)
1648 {
1649 struct dd_context *dctx = dd_context(_pipe);
1650 struct pipe_context *pipe = dctx->pipe;
1651 struct dd_draw_record *record =
1652 dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL;
1653
1654 if (record) {
1655 record->call.type = CALL_TRANSFER_UNMAP;
1656 record->call.info.transfer_unmap.transfer_ptr = transfer;
1657 record->call.info.transfer_unmap.transfer = *transfer;
1658 record->call.info.transfer_unmap.transfer.resource = NULL;
1659 pipe_resource_reference(
1660 &record->call.info.transfer_unmap.transfer.resource,
1661 transfer->resource);
1662
1663 dd_before_draw(dctx, record);
1664 }
1665 pipe->transfer_unmap(pipe, transfer);
1666 if (record)
1667 dd_after_draw(dctx, record);
1668 }
1669
1670 static void
1671 dd_context_buffer_subdata(struct pipe_context *_pipe,
1672 struct pipe_resource *resource,
1673 unsigned usage, unsigned offset,
1674 unsigned size, const void *data)
1675 {
1676 struct dd_context *dctx = dd_context(_pipe);
1677 struct pipe_context *pipe = dctx->pipe;
1678 struct dd_draw_record *record =
1679 dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL;
1680
1681 if (record) {
1682 record->call.type = CALL_BUFFER_SUBDATA;
1683 record->call.info.buffer_subdata.resource = NULL;
1684 pipe_resource_reference(&record->call.info.buffer_subdata.resource, resource);
1685 record->call.info.buffer_subdata.usage = usage;
1686 record->call.info.buffer_subdata.offset = offset;
1687 record->call.info.buffer_subdata.size = size;
1688 record->call.info.buffer_subdata.data = data;
1689
1690 dd_before_draw(dctx, record);
1691 }
1692 pipe->buffer_subdata(pipe, resource, usage, offset, size, data);
1693 if (record)
1694 dd_after_draw(dctx, record);
1695 }
1696
1697 static void
1698 dd_context_texture_subdata(struct pipe_context *_pipe,
1699 struct pipe_resource *resource,
1700 unsigned level, unsigned usage,
1701 const struct pipe_box *box,
1702 const void *data, unsigned stride,
1703 unsigned layer_stride)
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_TEXTURE_SUBDATA;
1712 record->call.info.texture_subdata.resource = NULL;
1713 pipe_resource_reference(&record->call.info.texture_subdata.resource, resource);
1714 record->call.info.texture_subdata.level = level;
1715 record->call.info.texture_subdata.usage = usage;
1716 record->call.info.texture_subdata.box = *box;
1717 record->call.info.texture_subdata.data = data;
1718 record->call.info.texture_subdata.stride = stride;
1719 record->call.info.texture_subdata.layer_stride = layer_stride;
1720
1721 dd_before_draw(dctx, record);
1722 }
1723 pipe->texture_subdata(pipe, resource, level, usage, box, data,
1724 stride, layer_stride);
1725 if (record)
1726 dd_after_draw(dctx, record);
1727 }
1728
1729 void
1730 dd_init_draw_functions(struct dd_context *dctx)
1731 {
1732 CTX_INIT(flush);
1733 CTX_INIT(draw_vbo);
1734 CTX_INIT(launch_grid);
1735 CTX_INIT(resource_copy_region);
1736 CTX_INIT(blit);
1737 CTX_INIT(clear);
1738 CTX_INIT(clear_render_target);
1739 CTX_INIT(clear_depth_stencil);
1740 CTX_INIT(clear_buffer);
1741 CTX_INIT(clear_texture);
1742 CTX_INIT(flush_resource);
1743 CTX_INIT(generate_mipmap);
1744 CTX_INIT(get_query_result_resource);
1745 CTX_INIT(transfer_map);
1746 CTX_INIT(transfer_flush_region);
1747 CTX_INIT(transfer_unmap);
1748 CTX_INIT(buffer_subdata);
1749 CTX_INIT(texture_subdata);
1750 }