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