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