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(query_flags, info, flags);
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_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)1349 dd_context_draw_vertex_state(struct pipe_context *_pipe,
1350 struct pipe_vertex_state *state,
1351 uint32_t partial_velem_mask,
1352 struct pipe_draw_vertex_state_info info,
1353 const struct pipe_draw_start_count_bias *draws,
1354 unsigned num_draws)
1355 {
1356 struct dd_context *dctx = dd_context(_pipe);
1357 struct pipe_context *pipe = dctx->pipe;
1358 struct dd_draw_record *record = dd_create_record(dctx);
1359
1360 record->call.type = CALL_DRAW_VBO;
1361 memset(&record->call.info.draw_vbo.info, 0,
1362 sizeof(record->call.info.draw_vbo.info));
1363 record->call.info.draw_vbo.info.mode = info.mode;
1364 record->call.info.draw_vbo.info.index_size = 4;
1365 record->call.info.draw_vbo.info.instance_count = 1;
1366 record->call.info.draw_vbo.drawid_offset = 0;
1367 record->call.info.draw_vbo.draw = draws[0];
1368 record->call.info.draw_vbo.info.index.resource = NULL;
1369 pipe_resource_reference(&record->call.info.draw_vbo.info.index.resource,
1370 state->input.indexbuf);
1371 memset(&record->call.info.draw_vbo.indirect, 0,
1372 sizeof(record->call.info.draw_vbo.indirect));
1373
1374 dd_before_draw(dctx, record);
1375 pipe->draw_vertex_state(pipe, state, partial_velem_mask, info, draws, num_draws);
1376 dd_after_draw(dctx, record);
1377 }
1378
1379 static void
dd_context_launch_grid(struct pipe_context * _pipe,const struct pipe_grid_info * info)1380 dd_context_launch_grid(struct pipe_context *_pipe,
1381 const struct pipe_grid_info *info)
1382 {
1383 struct dd_context *dctx = dd_context(_pipe);
1384 struct pipe_context *pipe = dctx->pipe;
1385 struct dd_draw_record *record = dd_create_record(dctx);
1386
1387 record->call.type = CALL_LAUNCH_GRID;
1388 record->call.info.launch_grid = *info;
1389 record->call.info.launch_grid.indirect = NULL;
1390 pipe_resource_reference(&record->call.info.launch_grid.indirect, info->indirect);
1391
1392 dd_before_draw(dctx, record);
1393 pipe->launch_grid(pipe, info);
1394 dd_after_draw(dctx, record);
1395 }
1396
1397 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)1398 dd_context_resource_copy_region(struct pipe_context *_pipe,
1399 struct pipe_resource *dst, unsigned dst_level,
1400 unsigned dstx, unsigned dsty, unsigned dstz,
1401 struct pipe_resource *src, unsigned src_level,
1402 const struct pipe_box *src_box)
1403 {
1404 struct dd_context *dctx = dd_context(_pipe);
1405 struct pipe_context *pipe = dctx->pipe;
1406 struct dd_draw_record *record = dd_create_record(dctx);
1407
1408 record->call.type = CALL_RESOURCE_COPY_REGION;
1409 record->call.info.resource_copy_region.dst = NULL;
1410 pipe_resource_reference(&record->call.info.resource_copy_region.dst, dst);
1411 record->call.info.resource_copy_region.dst_level = dst_level;
1412 record->call.info.resource_copy_region.dstx = dstx;
1413 record->call.info.resource_copy_region.dsty = dsty;
1414 record->call.info.resource_copy_region.dstz = dstz;
1415 record->call.info.resource_copy_region.src = NULL;
1416 pipe_resource_reference(&record->call.info.resource_copy_region.src, src);
1417 record->call.info.resource_copy_region.src_level = src_level;
1418 record->call.info.resource_copy_region.src_box = *src_box;
1419
1420 dd_before_draw(dctx, record);
1421 pipe->resource_copy_region(pipe,
1422 dst, dst_level, dstx, dsty, dstz,
1423 src, src_level, src_box);
1424 dd_after_draw(dctx, record);
1425 }
1426
1427 static void
dd_context_blit(struct pipe_context * _pipe,const struct pipe_blit_info * info)1428 dd_context_blit(struct pipe_context *_pipe, const struct pipe_blit_info *info)
1429 {
1430 struct dd_context *dctx = dd_context(_pipe);
1431 struct pipe_context *pipe = dctx->pipe;
1432 struct dd_draw_record *record = dd_create_record(dctx);
1433
1434 record->call.type = CALL_BLIT;
1435 record->call.info.blit = *info;
1436 record->call.info.blit.dst.resource = NULL;
1437 pipe_resource_reference(&record->call.info.blit.dst.resource, info->dst.resource);
1438 record->call.info.blit.src.resource = NULL;
1439 pipe_resource_reference(&record->call.info.blit.src.resource, info->src.resource);
1440
1441 dd_before_draw(dctx, record);
1442 pipe->blit(pipe, info);
1443 dd_after_draw(dctx, record);
1444 }
1445
1446 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)1447 dd_context_generate_mipmap(struct pipe_context *_pipe,
1448 struct pipe_resource *res,
1449 enum pipe_format format,
1450 unsigned base_level,
1451 unsigned last_level,
1452 unsigned first_layer,
1453 unsigned last_layer)
1454 {
1455 struct dd_context *dctx = dd_context(_pipe);
1456 struct pipe_context *pipe = dctx->pipe;
1457 struct dd_draw_record *record = dd_create_record(dctx);
1458 bool result;
1459
1460 record->call.type = CALL_GENERATE_MIPMAP;
1461 record->call.info.generate_mipmap.res = NULL;
1462 pipe_resource_reference(&record->call.info.generate_mipmap.res, res);
1463 record->call.info.generate_mipmap.format = format;
1464 record->call.info.generate_mipmap.base_level = base_level;
1465 record->call.info.generate_mipmap.last_level = last_level;
1466 record->call.info.generate_mipmap.first_layer = first_layer;
1467 record->call.info.generate_mipmap.last_layer = last_layer;
1468
1469 dd_before_draw(dctx, record);
1470 result = pipe->generate_mipmap(pipe, res, format, base_level, last_level,
1471 first_layer, last_layer);
1472 dd_after_draw(dctx, record);
1473 return result;
1474 }
1475
1476 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)1477 dd_context_get_query_result_resource(struct pipe_context *_pipe,
1478 struct pipe_query *query,
1479 enum pipe_query_flags flags,
1480 enum pipe_query_value_type result_type,
1481 int index,
1482 struct pipe_resource *resource,
1483 unsigned offset)
1484 {
1485 struct dd_context *dctx = dd_context(_pipe);
1486 struct dd_query *dquery = dd_query(query);
1487 struct pipe_context *pipe = dctx->pipe;
1488 struct dd_draw_record *record = dd_create_record(dctx);
1489
1490 record->call.type = CALL_GET_QUERY_RESULT_RESOURCE;
1491 record->call.info.get_query_result_resource.query = query;
1492 record->call.info.get_query_result_resource.flags = flags;
1493 record->call.info.get_query_result_resource.result_type = result_type;
1494 record->call.info.get_query_result_resource.index = index;
1495 record->call.info.get_query_result_resource.resource = NULL;
1496 pipe_resource_reference(&record->call.info.get_query_result_resource.resource,
1497 resource);
1498 record->call.info.get_query_result_resource.offset = offset;
1499
1500 /* The query may be deleted by the time we need to print it. */
1501 record->call.info.get_query_result_resource.query_type = dquery->type;
1502
1503 dd_before_draw(dctx, record);
1504 pipe->get_query_result_resource(pipe, dquery->query, flags,
1505 result_type, index, resource, offset);
1506 dd_after_draw(dctx, record);
1507 }
1508
1509 static void
dd_context_flush_resource(struct pipe_context * _pipe,struct pipe_resource * resource)1510 dd_context_flush_resource(struct pipe_context *_pipe,
1511 struct pipe_resource *resource)
1512 {
1513 struct dd_context *dctx = dd_context(_pipe);
1514 struct pipe_context *pipe = dctx->pipe;
1515 struct dd_draw_record *record = dd_create_record(dctx);
1516
1517 record->call.type = CALL_FLUSH_RESOURCE;
1518 record->call.info.flush_resource = NULL;
1519 pipe_resource_reference(&record->call.info.flush_resource, resource);
1520
1521 dd_before_draw(dctx, record);
1522 pipe->flush_resource(pipe, resource);
1523 dd_after_draw(dctx, record);
1524 }
1525
1526 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)1527 dd_context_clear(struct pipe_context *_pipe, unsigned buffers, const struct pipe_scissor_state *scissor_state,
1528 const union pipe_color_union *color, double depth,
1529 unsigned stencil)
1530 {
1531 struct dd_context *dctx = dd_context(_pipe);
1532 struct pipe_context *pipe = dctx->pipe;
1533 struct dd_draw_record *record = dd_create_record(dctx);
1534
1535 record->call.type = CALL_CLEAR;
1536 record->call.info.clear.buffers = buffers;
1537 if (scissor_state)
1538 record->call.info.clear.scissor_state = *scissor_state;
1539 record->call.info.clear.color = *color;
1540 record->call.info.clear.depth = depth;
1541 record->call.info.clear.stencil = stencil;
1542
1543 dd_before_draw(dctx, record);
1544 pipe->clear(pipe, buffers, scissor_state, color, depth, stencil);
1545 dd_after_draw(dctx, record);
1546 }
1547
1548 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)1549 dd_context_clear_render_target(struct pipe_context *_pipe,
1550 struct pipe_surface *dst,
1551 const union pipe_color_union *color,
1552 unsigned dstx, unsigned dsty,
1553 unsigned width, unsigned height,
1554 bool render_condition_enabled)
1555 {
1556 struct dd_context *dctx = dd_context(_pipe);
1557 struct pipe_context *pipe = dctx->pipe;
1558 struct dd_draw_record *record = dd_create_record(dctx);
1559
1560 record->call.type = CALL_CLEAR_RENDER_TARGET;
1561
1562 dd_before_draw(dctx, record);
1563 pipe->clear_render_target(pipe, dst, color, dstx, dsty, width, height,
1564 render_condition_enabled);
1565 dd_after_draw(dctx, record);
1566 }
1567
1568 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)1569 dd_context_clear_depth_stencil(struct pipe_context *_pipe,
1570 struct pipe_surface *dst, unsigned clear_flags,
1571 double depth, unsigned stencil, unsigned dstx,
1572 unsigned dsty, unsigned width, unsigned height,
1573 bool render_condition_enabled)
1574 {
1575 struct dd_context *dctx = dd_context(_pipe);
1576 struct pipe_context *pipe = dctx->pipe;
1577 struct dd_draw_record *record = dd_create_record(dctx);
1578
1579 record->call.type = CALL_CLEAR_DEPTH_STENCIL;
1580
1581 dd_before_draw(dctx, record);
1582 pipe->clear_depth_stencil(pipe, dst, clear_flags, depth, stencil,
1583 dstx, dsty, width, height,
1584 render_condition_enabled);
1585 dd_after_draw(dctx, record);
1586 }
1587
1588 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)1589 dd_context_clear_buffer(struct pipe_context *_pipe, struct pipe_resource *res,
1590 unsigned offset, unsigned size,
1591 const void *clear_value, int clear_value_size)
1592 {
1593 struct dd_context *dctx = dd_context(_pipe);
1594 struct pipe_context *pipe = dctx->pipe;
1595 struct dd_draw_record *record = dd_create_record(dctx);
1596
1597 record->call.type = CALL_CLEAR_BUFFER;
1598 record->call.info.clear_buffer.res = NULL;
1599 pipe_resource_reference(&record->call.info.clear_buffer.res, res);
1600 record->call.info.clear_buffer.offset = offset;
1601 record->call.info.clear_buffer.size = size;
1602 record->call.info.clear_buffer.clear_value = clear_value;
1603 record->call.info.clear_buffer.clear_value_size = clear_value_size;
1604
1605 dd_before_draw(dctx, record);
1606 pipe->clear_buffer(pipe, res, offset, size, clear_value, clear_value_size);
1607 dd_after_draw(dctx, record);
1608 }
1609
1610 static void
dd_context_clear_texture(struct pipe_context * _pipe,struct pipe_resource * res,unsigned level,const struct pipe_box * box,const void * data)1611 dd_context_clear_texture(struct pipe_context *_pipe,
1612 struct pipe_resource *res,
1613 unsigned level,
1614 const struct pipe_box *box,
1615 const void *data)
1616 {
1617 struct dd_context *dctx = dd_context(_pipe);
1618 struct pipe_context *pipe = dctx->pipe;
1619 struct dd_draw_record *record = dd_create_record(dctx);
1620
1621 record->call.type = CALL_CLEAR_TEXTURE;
1622
1623 dd_before_draw(dctx, record);
1624 pipe->clear_texture(pipe, res, level, box, data);
1625 dd_after_draw(dctx, record);
1626 }
1627
1628 /********************************************************************
1629 * transfer
1630 */
1631
1632 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)1633 dd_context_buffer_map(struct pipe_context *_pipe,
1634 struct pipe_resource *resource, unsigned level,
1635 unsigned usage, const struct pipe_box *box,
1636 struct pipe_transfer **transfer)
1637 {
1638 struct dd_context *dctx = dd_context(_pipe);
1639 struct pipe_context *pipe = dctx->pipe;
1640 struct dd_draw_record *record =
1641 dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL;
1642
1643 if (record) {
1644 record->call.type = CALL_TRANSFER_MAP;
1645
1646 dd_before_draw(dctx, record);
1647 }
1648 void *ptr = pipe->buffer_map(pipe, resource, level, usage, box, transfer);
1649 if (record) {
1650 record->call.info.transfer_map.transfer_ptr = *transfer;
1651 record->call.info.transfer_map.ptr = ptr;
1652 if (*transfer) {
1653 record->call.info.transfer_map.transfer = **transfer;
1654 record->call.info.transfer_map.transfer.resource = NULL;
1655 pipe_resource_reference(&record->call.info.transfer_map.transfer.resource,
1656 (*transfer)->resource);
1657 } else {
1658 memset(&record->call.info.transfer_map.transfer, 0, sizeof(struct pipe_transfer));
1659 }
1660
1661 dd_after_draw(dctx, record);
1662 }
1663 return ptr;
1664 }
1665
1666 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)1667 dd_context_texture_map(struct pipe_context *_pipe,
1668 struct pipe_resource *resource, unsigned level,
1669 unsigned usage, const struct pipe_box *box,
1670 struct pipe_transfer **transfer)
1671 {
1672 struct dd_context *dctx = dd_context(_pipe);
1673 struct pipe_context *pipe = dctx->pipe;
1674 struct dd_draw_record *record =
1675 dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL;
1676
1677 if (record) {
1678 record->call.type = CALL_TRANSFER_MAP;
1679
1680 dd_before_draw(dctx, record);
1681 }
1682 void *ptr = pipe->texture_map(pipe, resource, level, usage, box, transfer);
1683 if (record) {
1684 record->call.info.transfer_map.transfer_ptr = *transfer;
1685 record->call.info.transfer_map.ptr = ptr;
1686 if (*transfer) {
1687 record->call.info.transfer_map.transfer = **transfer;
1688 record->call.info.transfer_map.transfer.resource = NULL;
1689 pipe_resource_reference(&record->call.info.transfer_map.transfer.resource,
1690 (*transfer)->resource);
1691 } else {
1692 memset(&record->call.info.transfer_map.transfer, 0, sizeof(struct pipe_transfer));
1693 }
1694
1695 dd_after_draw(dctx, record);
1696 }
1697 return ptr;
1698 }
1699
1700 static void
dd_context_transfer_flush_region(struct pipe_context * _pipe,struct pipe_transfer * transfer,const struct pipe_box * box)1701 dd_context_transfer_flush_region(struct pipe_context *_pipe,
1702 struct pipe_transfer *transfer,
1703 const struct pipe_box *box)
1704 {
1705 struct dd_context *dctx = dd_context(_pipe);
1706 struct pipe_context *pipe = dctx->pipe;
1707 struct dd_draw_record *record =
1708 dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL;
1709
1710 if (record) {
1711 record->call.type = CALL_TRANSFER_FLUSH_REGION;
1712 record->call.info.transfer_flush_region.transfer_ptr = transfer;
1713 record->call.info.transfer_flush_region.box = *box;
1714 record->call.info.transfer_flush_region.transfer = *transfer;
1715 record->call.info.transfer_flush_region.transfer.resource = NULL;
1716 pipe_resource_reference(
1717 &record->call.info.transfer_flush_region.transfer.resource,
1718 transfer->resource);
1719
1720 dd_before_draw(dctx, record);
1721 }
1722 pipe->transfer_flush_region(pipe, transfer, box);
1723 if (record)
1724 dd_after_draw(dctx, record);
1725 }
1726
1727 static void
dd_context_buffer_unmap(struct pipe_context * _pipe,struct pipe_transfer * transfer)1728 dd_context_buffer_unmap(struct pipe_context *_pipe,
1729 struct pipe_transfer *transfer)
1730 {
1731 struct dd_context *dctx = dd_context(_pipe);
1732 struct pipe_context *pipe = dctx->pipe;
1733 struct dd_draw_record *record =
1734 dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL;
1735
1736 if (record) {
1737 record->call.type = CALL_TRANSFER_UNMAP;
1738 record->call.info.transfer_unmap.transfer_ptr = transfer;
1739 record->call.info.transfer_unmap.transfer = *transfer;
1740 record->call.info.transfer_unmap.transfer.resource = NULL;
1741 pipe_resource_reference(
1742 &record->call.info.transfer_unmap.transfer.resource,
1743 transfer->resource);
1744
1745 dd_before_draw(dctx, record);
1746 }
1747 pipe->buffer_unmap(pipe, transfer);
1748 if (record)
1749 dd_after_draw(dctx, record);
1750 }
1751
1752 static void
dd_context_texture_unmap(struct pipe_context * _pipe,struct pipe_transfer * transfer)1753 dd_context_texture_unmap(struct pipe_context *_pipe,
1754 struct pipe_transfer *transfer)
1755 {
1756 struct dd_context *dctx = dd_context(_pipe);
1757 struct pipe_context *pipe = dctx->pipe;
1758 struct dd_draw_record *record =
1759 dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL;
1760
1761 if (record) {
1762 record->call.type = CALL_TRANSFER_UNMAP;
1763 record->call.info.transfer_unmap.transfer_ptr = transfer;
1764 record->call.info.transfer_unmap.transfer = *transfer;
1765 record->call.info.transfer_unmap.transfer.resource = NULL;
1766 pipe_resource_reference(
1767 &record->call.info.transfer_unmap.transfer.resource,
1768 transfer->resource);
1769
1770 dd_before_draw(dctx, record);
1771 }
1772 pipe->texture_unmap(pipe, transfer);
1773 if (record)
1774 dd_after_draw(dctx, record);
1775 }
1776
1777 static void
dd_context_buffer_subdata(struct pipe_context * _pipe,struct pipe_resource * resource,unsigned usage,unsigned offset,unsigned size,const void * data)1778 dd_context_buffer_subdata(struct pipe_context *_pipe,
1779 struct pipe_resource *resource,
1780 unsigned usage, unsigned offset,
1781 unsigned size, const void *data)
1782 {
1783 struct dd_context *dctx = dd_context(_pipe);
1784 struct pipe_context *pipe = dctx->pipe;
1785 struct dd_draw_record *record =
1786 dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL;
1787
1788 if (record) {
1789 record->call.type = CALL_BUFFER_SUBDATA;
1790 record->call.info.buffer_subdata.resource = NULL;
1791 pipe_resource_reference(&record->call.info.buffer_subdata.resource, resource);
1792 record->call.info.buffer_subdata.usage = usage;
1793 record->call.info.buffer_subdata.offset = offset;
1794 record->call.info.buffer_subdata.size = size;
1795 record->call.info.buffer_subdata.data = data;
1796
1797 dd_before_draw(dctx, record);
1798 }
1799 pipe->buffer_subdata(pipe, resource, usage, offset, size, data);
1800 if (record)
1801 dd_after_draw(dctx, record);
1802 }
1803
1804 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)1805 dd_context_texture_subdata(struct pipe_context *_pipe,
1806 struct pipe_resource *resource,
1807 unsigned level, unsigned usage,
1808 const struct pipe_box *box,
1809 const void *data, unsigned stride,
1810 unsigned layer_stride)
1811 {
1812 struct dd_context *dctx = dd_context(_pipe);
1813 struct pipe_context *pipe = dctx->pipe;
1814 struct dd_draw_record *record =
1815 dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL;
1816
1817 if (record) {
1818 record->call.type = CALL_TEXTURE_SUBDATA;
1819 record->call.info.texture_subdata.resource = NULL;
1820 pipe_resource_reference(&record->call.info.texture_subdata.resource, resource);
1821 record->call.info.texture_subdata.level = level;
1822 record->call.info.texture_subdata.usage = usage;
1823 record->call.info.texture_subdata.box = *box;
1824 record->call.info.texture_subdata.data = data;
1825 record->call.info.texture_subdata.stride = stride;
1826 record->call.info.texture_subdata.layer_stride = layer_stride;
1827
1828 dd_before_draw(dctx, record);
1829 }
1830 pipe->texture_subdata(pipe, resource, level, usage, box, data,
1831 stride, layer_stride);
1832 if (record)
1833 dd_after_draw(dctx, record);
1834 }
1835
1836 void
dd_init_draw_functions(struct dd_context * dctx)1837 dd_init_draw_functions(struct dd_context *dctx)
1838 {
1839 CTX_INIT(flush);
1840 CTX_INIT(draw_vbo);
1841 CTX_INIT(launch_grid);
1842 CTX_INIT(resource_copy_region);
1843 CTX_INIT(blit);
1844 CTX_INIT(clear);
1845 CTX_INIT(clear_render_target);
1846 CTX_INIT(clear_depth_stencil);
1847 CTX_INIT(clear_buffer);
1848 CTX_INIT(clear_texture);
1849 CTX_INIT(flush_resource);
1850 CTX_INIT(generate_mipmap);
1851 CTX_INIT(get_query_result_resource);
1852 CTX_INIT(buffer_map);
1853 CTX_INIT(texture_map);
1854 CTX_INIT(transfer_flush_region);
1855 CTX_INIT(buffer_unmap);
1856 CTX_INIT(texture_unmap);
1857 CTX_INIT(buffer_subdata);
1858 CTX_INIT(texture_subdata);
1859 CTX_INIT(draw_vertex_state);
1860 }
1861