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