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