• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**************************************************************************
2  *
3  * Copyright 2015 Advanced Micro Devices, Inc.
4  * Copyright 2008 VMware, Inc.
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * on the rights to use, copy, modify, merge, publish, distribute, sub
11  * license, and/or sell copies of the Software, and to permit persons to whom
12  * the Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the next
15  * paragraph) shall be included in all copies or substantial portions of the
16  * Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24  * USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  **************************************************************************/
27 
28 #include "dd_pipe.h"
29 
30 #include "util/u_dump.h"
31 #include "util/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 "os/os_time.h"
39 #include <inttypes.h>
40 
41 
42 static FILE *
dd_get_file_stream(struct dd_screen * dscreen,unsigned apitrace_call_number)43 dd_get_file_stream(struct dd_screen *dscreen, unsigned apitrace_call_number)
44 {
45    struct pipe_screen *screen = dscreen->screen;
46    char cmd_line[4096];
47 
48    FILE *f = dd_get_debug_file(dscreen->verbose);
49    if (!f)
50       return NULL;
51 
52    if (os_get_command_line(cmd_line, sizeof(cmd_line)))
53       fprintf(f, "Command: %s\n", cmd_line);
54    fprintf(f, "Driver vendor: %s\n", screen->get_vendor(screen));
55    fprintf(f, "Device vendor: %s\n", screen->get_device_vendor(screen));
56    fprintf(f, "Device name: %s\n\n", screen->get_name(screen));
57 
58    if (apitrace_call_number)
59       fprintf(f, "Last apitrace call: %u\n\n",
60               apitrace_call_number);
61    return f;
62 }
63 
64 static void
dd_dump_dmesg(FILE * f)65 dd_dump_dmesg(FILE *f)
66 {
67    char line[2000];
68    FILE *p = popen("dmesg | tail -n60", "r");
69 
70    if (!p)
71       return;
72 
73    fprintf(f, "\nLast 60 lines of dmesg:\n\n");
74    while (fgets(line, sizeof(line), p))
75       fputs(line, f);
76 
77    pclose(p);
78 }
79 
80 static void
dd_close_file_stream(FILE * f)81 dd_close_file_stream(FILE *f)
82 {
83    fclose(f);
84 }
85 
86 static unsigned
dd_num_active_viewports(struct dd_draw_state * dstate)87 dd_num_active_viewports(struct dd_draw_state *dstate)
88 {
89    struct tgsi_shader_info info;
90    const struct tgsi_token *tokens;
91 
92    if (dstate->shaders[PIPE_SHADER_GEOMETRY])
93       tokens = dstate->shaders[PIPE_SHADER_GEOMETRY]->state.shader.tokens;
94    else if (dstate->shaders[PIPE_SHADER_TESS_EVAL])
95       tokens = dstate->shaders[PIPE_SHADER_TESS_EVAL]->state.shader.tokens;
96    else if (dstate->shaders[PIPE_SHADER_VERTEX])
97       tokens = dstate->shaders[PIPE_SHADER_VERTEX]->state.shader.tokens;
98    else
99       return 1;
100 
101    tgsi_scan_shader(tokens, &info);
102    return info.writes_viewport_index ? PIPE_MAX_VIEWPORTS : 1;
103 }
104 
105 #define COLOR_RESET	"\033[0m"
106 #define COLOR_SHADER	"\033[1;32m"
107 #define COLOR_STATE	"\033[1;33m"
108 
109 #define DUMP(name, var) do { \
110    fprintf(f, COLOR_STATE #name ": " COLOR_RESET); \
111    util_dump_##name(f, var); \
112    fprintf(f, "\n"); \
113 } while(0)
114 
115 #define DUMP_I(name, var, i) do { \
116    fprintf(f, COLOR_STATE #name " %i: " COLOR_RESET, i); \
117    util_dump_##name(f, var); \
118    fprintf(f, "\n"); \
119 } while(0)
120 
121 #define DUMP_M(name, var, member) do { \
122    fprintf(f, "  " #member ": "); \
123    util_dump_##name(f, (var)->member); \
124    fprintf(f, "\n"); \
125 } while(0)
126 
127 #define DUMP_M_ADDR(name, var, member) do { \
128    fprintf(f, "  " #member ": "); \
129    util_dump_##name(f, &(var)->member); \
130    fprintf(f, "\n"); \
131 } while(0)
132 
133 static void
print_named_value(FILE * f,const char * name,int value)134 print_named_value(FILE *f, const char *name, int value)
135 {
136    fprintf(f, COLOR_STATE "%s" COLOR_RESET " = %i\n", name, value);
137 }
138 
139 static void
print_named_xvalue(FILE * f,const char * name,int value)140 print_named_xvalue(FILE *f, const char *name, int value)
141 {
142    fprintf(f, COLOR_STATE "%s" COLOR_RESET " = 0x%08x\n", name, value);
143 }
144 
145 static void
util_dump_uint(FILE * f,unsigned i)146 util_dump_uint(FILE *f, unsigned i)
147 {
148    fprintf(f, "%u", i);
149 }
150 
151 static void
util_dump_hex(FILE * f,unsigned i)152 util_dump_hex(FILE *f, unsigned i)
153 {
154    fprintf(f, "0x%x", i);
155 }
156 
157 static void
util_dump_double(FILE * f,double d)158 util_dump_double(FILE *f, double d)
159 {
160    fprintf(f, "%f", d);
161 }
162 
163 static void
util_dump_format(FILE * f,enum pipe_format format)164 util_dump_format(FILE *f, enum pipe_format format)
165 {
166    fprintf(f, "%s", util_format_name(format));
167 }
168 
169 static void
util_dump_color_union(FILE * f,const union pipe_color_union * color)170 util_dump_color_union(FILE *f, const union pipe_color_union *color)
171 {
172    fprintf(f, "{f = {%f, %f, %f, %f}, ui = {%u, %u, %u, %u}",
173            color->f[0], color->f[1], color->f[2], color->f[3],
174            color->ui[0], color->ui[1], color->ui[2], color->ui[3]);
175 }
176 
177 static void
util_dump_query(FILE * f,struct dd_query * query)178 util_dump_query(FILE *f, struct dd_query *query)
179 {
180    if (query->type >= PIPE_QUERY_DRIVER_SPECIFIC)
181       fprintf(f, "PIPE_QUERY_DRIVER_SPECIFIC + %i",
182               query->type - PIPE_QUERY_DRIVER_SPECIFIC);
183    else
184       fprintf(f, "%s", util_dump_query_type(query->type, false));
185 }
186 
187 static void
dd_dump_render_condition(struct dd_draw_state * dstate,FILE * f)188 dd_dump_render_condition(struct dd_draw_state *dstate, FILE *f)
189 {
190    if (dstate->render_cond.query) {
191       fprintf(f, "render condition:\n");
192       DUMP_M(query, &dstate->render_cond, query);
193       DUMP_M(uint, &dstate->render_cond, condition);
194       DUMP_M(uint, &dstate->render_cond, mode);
195       fprintf(f, "\n");
196    }
197 }
198 
199 static void
dd_dump_draw_vbo(struct dd_draw_state * dstate,struct pipe_draw_info * info,FILE * f)200 dd_dump_draw_vbo(struct dd_draw_state *dstate, struct pipe_draw_info *info, FILE *f)
201 {
202    int sh, i;
203    const char *shader_str[PIPE_SHADER_TYPES];
204 
205    shader_str[PIPE_SHADER_VERTEX] = "VERTEX";
206    shader_str[PIPE_SHADER_TESS_CTRL] = "TESS_CTRL";
207    shader_str[PIPE_SHADER_TESS_EVAL] = "TESS_EVAL";
208    shader_str[PIPE_SHADER_GEOMETRY] = "GEOMETRY";
209    shader_str[PIPE_SHADER_FRAGMENT] = "FRAGMENT";
210    shader_str[PIPE_SHADER_COMPUTE] = "COMPUTE";
211 
212    DUMP(draw_info, info);
213    if (info->indexed) {
214       DUMP(index_buffer, &dstate->index_buffer);
215       if (dstate->index_buffer.buffer)
216          DUMP_M(resource, &dstate->index_buffer, buffer);
217    }
218    if (info->count_from_stream_output)
219       DUMP_M(stream_output_target, info,
220              count_from_stream_output);
221    if (info->indirect)
222       DUMP_M(resource, info, indirect);
223    fprintf(f, "\n");
224 
225    /* TODO: dump active queries */
226 
227    dd_dump_render_condition(dstate, f);
228 
229    for (i = 0; i < PIPE_MAX_ATTRIBS; i++)
230       if (dstate->vertex_buffers[i].buffer ||
231           dstate->vertex_buffers[i].user_buffer) {
232          DUMP_I(vertex_buffer, &dstate->vertex_buffers[i], i);
233          if (dstate->vertex_buffers[i].buffer)
234             DUMP_M(resource, &dstate->vertex_buffers[i], buffer);
235       }
236 
237    if (dstate->velems) {
238       print_named_value(f, "num vertex elements",
239                         dstate->velems->state.velems.count);
240       for (i = 0; i < dstate->velems->state.velems.count; i++) {
241          fprintf(f, "  ");
242          DUMP_I(vertex_element, &dstate->velems->state.velems.velems[i], i);
243       }
244    }
245 
246    print_named_value(f, "num stream output targets", dstate->num_so_targets);
247    for (i = 0; i < dstate->num_so_targets; i++)
248       if (dstate->so_targets[i]) {
249          DUMP_I(stream_output_target, dstate->so_targets[i], i);
250          DUMP_M(resource, dstate->so_targets[i], buffer);
251          fprintf(f, "  offset = %i\n", dstate->so_offsets[i]);
252       }
253 
254    fprintf(f, "\n");
255    for (sh = 0; sh < PIPE_SHADER_TYPES; sh++) {
256       if (sh == PIPE_SHADER_COMPUTE)
257          continue;
258 
259       if (sh == PIPE_SHADER_TESS_CTRL &&
260           !dstate->shaders[PIPE_SHADER_TESS_CTRL] &&
261           dstate->shaders[PIPE_SHADER_TESS_EVAL])
262          fprintf(f, "tess_state: {default_outer_level = {%f, %f, %f, %f}, "
263                  "default_inner_level = {%f, %f}}\n",
264                  dstate->tess_default_levels[0],
265                  dstate->tess_default_levels[1],
266                  dstate->tess_default_levels[2],
267                  dstate->tess_default_levels[3],
268                  dstate->tess_default_levels[4],
269                  dstate->tess_default_levels[5]);
270 
271       if (sh == PIPE_SHADER_FRAGMENT)
272          if (dstate->rs) {
273             unsigned num_viewports = dd_num_active_viewports(dstate);
274 
275             if (dstate->rs->state.rs.clip_plane_enable)
276                DUMP(clip_state, &dstate->clip_state);
277 
278             for (i = 0; i < num_viewports; i++)
279                DUMP_I(viewport_state, &dstate->viewports[i], i);
280 
281             if (dstate->rs->state.rs.scissor)
282                for (i = 0; i < num_viewports; i++)
283                   DUMP_I(scissor_state, &dstate->scissors[i], i);
284 
285             DUMP(rasterizer_state, &dstate->rs->state.rs);
286 
287             if (dstate->rs->state.rs.poly_stipple_enable)
288                DUMP(poly_stipple, &dstate->polygon_stipple);
289             fprintf(f, "\n");
290          }
291 
292       if (!dstate->shaders[sh])
293          continue;
294 
295       fprintf(f, COLOR_SHADER "begin shader: %s" COLOR_RESET "\n", shader_str[sh]);
296       DUMP(shader_state, &dstate->shaders[sh]->state.shader);
297 
298       for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++)
299          if (dstate->constant_buffers[sh][i].buffer ||
300              dstate->constant_buffers[sh][i].user_buffer) {
301             DUMP_I(constant_buffer, &dstate->constant_buffers[sh][i], i);
302             if (dstate->constant_buffers[sh][i].buffer)
303                DUMP_M(resource, &dstate->constant_buffers[sh][i], buffer);
304          }
305 
306       for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
307          if (dstate->sampler_states[sh][i])
308             DUMP_I(sampler_state, &dstate->sampler_states[sh][i]->state.sampler, i);
309 
310       for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
311          if (dstate->sampler_views[sh][i]) {
312             DUMP_I(sampler_view, dstate->sampler_views[sh][i], i);
313             DUMP_M(resource, dstate->sampler_views[sh][i], texture);
314          }
315 
316       for (i = 0; i < PIPE_MAX_SHADER_IMAGES; i++)
317          if (dstate->shader_images[sh][i].resource) {
318             DUMP_I(image_view, &dstate->shader_images[sh][i], i);
319             if (dstate->shader_images[sh][i].resource)
320                DUMP_M(resource, &dstate->shader_images[sh][i], resource);
321          }
322 
323       for (i = 0; i < PIPE_MAX_SHADER_BUFFERS; i++)
324          if (dstate->shader_buffers[sh][i].buffer) {
325             DUMP_I(shader_buffer, &dstate->shader_buffers[sh][i], i);
326             if (dstate->shader_buffers[sh][i].buffer)
327                DUMP_M(resource, &dstate->shader_buffers[sh][i], buffer);
328          }
329 
330       fprintf(f, COLOR_SHADER "end shader: %s" COLOR_RESET "\n\n", shader_str[sh]);
331    }
332 
333    if (dstate->dsa)
334       DUMP(depth_stencil_alpha_state, &dstate->dsa->state.dsa);
335    DUMP(stencil_ref, &dstate->stencil_ref);
336 
337    if (dstate->blend)
338       DUMP(blend_state, &dstate->blend->state.blend);
339    DUMP(blend_color, &dstate->blend_color);
340 
341    print_named_value(f, "min_samples", dstate->min_samples);
342    print_named_xvalue(f, "sample_mask", dstate->sample_mask);
343    fprintf(f, "\n");
344 
345    DUMP(framebuffer_state, &dstate->framebuffer_state);
346    for (i = 0; i < dstate->framebuffer_state.nr_cbufs; i++)
347       if (dstate->framebuffer_state.cbufs[i]) {
348          fprintf(f, "  " COLOR_STATE "cbufs[%i]:" COLOR_RESET "\n    ", i);
349          DUMP(surface, dstate->framebuffer_state.cbufs[i]);
350          fprintf(f, "    ");
351          DUMP(resource, dstate->framebuffer_state.cbufs[i]->texture);
352       }
353    if (dstate->framebuffer_state.zsbuf) {
354       fprintf(f, "  " COLOR_STATE "zsbuf:" COLOR_RESET "\n    ");
355       DUMP(surface, dstate->framebuffer_state.zsbuf);
356       fprintf(f, "    ");
357       DUMP(resource, dstate->framebuffer_state.zsbuf->texture);
358    }
359    fprintf(f, "\n");
360 }
361 
362 static void
dd_dump_launch_grid(struct dd_draw_state * dstate,struct pipe_grid_info * info,FILE * f)363 dd_dump_launch_grid(struct dd_draw_state *dstate, struct pipe_grid_info *info, FILE *f)
364 {
365    fprintf(f, "%s:\n", __func__+8);
366    /* TODO */
367 }
368 
369 static void
dd_dump_resource_copy_region(struct dd_draw_state * dstate,struct call_resource_copy_region * info,FILE * f)370 dd_dump_resource_copy_region(struct dd_draw_state *dstate,
371                              struct call_resource_copy_region *info,
372                              FILE *f)
373 {
374    fprintf(f, "%s:\n", __func__+8);
375    DUMP_M(resource, info, dst);
376    DUMP_M(uint, info, dst_level);
377    DUMP_M(uint, info, dstx);
378    DUMP_M(uint, info, dsty);
379    DUMP_M(uint, info, dstz);
380    DUMP_M(resource, info, src);
381    DUMP_M(uint, info, src_level);
382    DUMP_M_ADDR(box, info, src_box);
383 }
384 
385 static void
dd_dump_blit(struct dd_draw_state * dstate,struct pipe_blit_info * info,FILE * f)386 dd_dump_blit(struct dd_draw_state *dstate, struct pipe_blit_info *info, FILE *f)
387 {
388    fprintf(f, "%s:\n", __func__+8);
389    DUMP_M(resource, info, dst.resource);
390    DUMP_M(uint, info, dst.level);
391    DUMP_M_ADDR(box, info, dst.box);
392    DUMP_M(format, info, dst.format);
393 
394    DUMP_M(resource, info, src.resource);
395    DUMP_M(uint, info, src.level);
396    DUMP_M_ADDR(box, info, src.box);
397    DUMP_M(format, info, src.format);
398 
399    DUMP_M(hex, info, mask);
400    DUMP_M(uint, info, filter);
401    DUMP_M(uint, info, scissor_enable);
402    DUMP_M_ADDR(scissor_state, info, scissor);
403    DUMP_M(uint, info, render_condition_enable);
404 
405    if (info->render_condition_enable)
406       dd_dump_render_condition(dstate, f);
407 }
408 
409 static void
dd_dump_generate_mipmap(struct dd_draw_state * dstate,FILE * f)410 dd_dump_generate_mipmap(struct dd_draw_state *dstate, FILE *f)
411 {
412    fprintf(f, "%s:\n", __func__+8);
413    /* TODO */
414 }
415 
416 static void
dd_dump_flush_resource(struct dd_draw_state * dstate,struct pipe_resource * res,FILE * f)417 dd_dump_flush_resource(struct dd_draw_state *dstate, struct pipe_resource *res,
418                        FILE *f)
419 {
420    fprintf(f, "%s:\n", __func__+8);
421    DUMP(resource, res);
422 }
423 
424 static void
dd_dump_clear(struct dd_draw_state * dstate,struct call_clear * info,FILE * f)425 dd_dump_clear(struct dd_draw_state *dstate, struct call_clear *info, FILE *f)
426 {
427    fprintf(f, "%s:\n", __func__+8);
428    DUMP_M(uint, info, buffers);
429    DUMP_M_ADDR(color_union, info, color);
430    DUMP_M(double, info, depth);
431    DUMP_M(hex, info, stencil);
432 }
433 
434 static void
dd_dump_clear_buffer(struct dd_draw_state * dstate,struct call_clear_buffer * info,FILE * f)435 dd_dump_clear_buffer(struct dd_draw_state *dstate, struct call_clear_buffer *info,
436                      FILE *f)
437 {
438    int i;
439    const char *value = (const char*)info->clear_value;
440 
441    fprintf(f, "%s:\n", __func__+8);
442    DUMP_M(resource, info, res);
443    DUMP_M(uint, info, offset);
444    DUMP_M(uint, info, size);
445    DUMP_M(uint, info, clear_value_size);
446 
447    fprintf(f, "  clear_value:");
448    for (i = 0; i < info->clear_value_size; i++)
449       fprintf(f, " %02x", value[i]);
450    fprintf(f, "\n");
451 }
452 
453 static void
dd_dump_clear_render_target(struct dd_draw_state * dstate,FILE * f)454 dd_dump_clear_render_target(struct dd_draw_state *dstate, FILE *f)
455 {
456    fprintf(f, "%s:\n", __func__+8);
457    /* TODO */
458 }
459 
460 static void
dd_dump_clear_depth_stencil(struct dd_draw_state * dstate,FILE * f)461 dd_dump_clear_depth_stencil(struct dd_draw_state *dstate, FILE *f)
462 {
463    fprintf(f, "%s:\n", __func__+8);
464    /* TODO */
465 }
466 
467 static void
dd_dump_driver_state(struct dd_context * dctx,FILE * f,unsigned flags)468 dd_dump_driver_state(struct dd_context *dctx, FILE *f, unsigned flags)
469 {
470    if (dctx->pipe->dump_debug_state) {
471 	   fprintf(f,"\n\n**************************************************"
472 		     "***************************\n");
473 	   fprintf(f, "Driver-specific state:\n\n");
474 	   dctx->pipe->dump_debug_state(dctx->pipe, f, flags);
475    }
476 }
477 
478 static void
dd_dump_call(FILE * f,struct dd_draw_state * state,struct dd_call * call)479 dd_dump_call(FILE *f, struct dd_draw_state *state, struct dd_call *call)
480 {
481    switch (call->type) {
482    case CALL_DRAW_VBO:
483       dd_dump_draw_vbo(state, &call->info.draw_vbo, f);
484       break;
485    case CALL_LAUNCH_GRID:
486       dd_dump_launch_grid(state, &call->info.launch_grid, f);
487       break;
488    case CALL_RESOURCE_COPY_REGION:
489       dd_dump_resource_copy_region(state,
490                                    &call->info.resource_copy_region, f);
491       break;
492    case CALL_BLIT:
493       dd_dump_blit(state, &call->info.blit, f);
494       break;
495    case CALL_FLUSH_RESOURCE:
496       dd_dump_flush_resource(state, call->info.flush_resource, f);
497       break;
498    case CALL_CLEAR:
499       dd_dump_clear(state, &call->info.clear, f);
500       break;
501    case CALL_CLEAR_BUFFER:
502       dd_dump_clear_buffer(state, &call->info.clear_buffer, f);
503       break;
504    case CALL_CLEAR_RENDER_TARGET:
505       dd_dump_clear_render_target(state, f);
506       break;
507    case CALL_CLEAR_DEPTH_STENCIL:
508       dd_dump_clear_depth_stencil(state, f);
509       break;
510    case CALL_GENERATE_MIPMAP:
511       dd_dump_generate_mipmap(state, f);
512       break;
513    }
514 }
515 
516 static void
dd_write_report(struct dd_context * dctx,struct dd_call * call,unsigned flags,bool dump_dmesg)517 dd_write_report(struct dd_context *dctx, struct dd_call *call, unsigned flags,
518                 bool dump_dmesg)
519 {
520    FILE *f = dd_get_file_stream(dd_screen(dctx->base.screen),
521                                 dctx->draw_state.apitrace_call_number);
522 
523    if (!f)
524       return;
525 
526    dd_dump_call(f, &dctx->draw_state, call);
527    dd_dump_driver_state(dctx, f, flags);
528    if (dump_dmesg)
529       dd_dump_dmesg(f);
530    dd_close_file_stream(f);
531 }
532 
533 static void
dd_kill_process(void)534 dd_kill_process(void)
535 {
536    sync();
537    fprintf(stderr, "dd: Aborting the process...\n");
538    fflush(stdout);
539    fflush(stderr);
540    exit(1);
541 }
542 
543 static bool
dd_flush_and_check_hang(struct dd_context * dctx,struct pipe_fence_handle ** flush_fence,unsigned flush_flags)544 dd_flush_and_check_hang(struct dd_context *dctx,
545                         struct pipe_fence_handle **flush_fence,
546                         unsigned flush_flags)
547 {
548    struct pipe_fence_handle *fence = NULL;
549    struct pipe_context *pipe = dctx->pipe;
550    struct pipe_screen *screen = pipe->screen;
551    uint64_t timeout_ms = dd_screen(dctx->base.screen)->timeout_ms;
552    bool idle;
553 
554    assert(timeout_ms > 0);
555 
556    pipe->flush(pipe, &fence, flush_flags);
557    if (flush_fence)
558       screen->fence_reference(screen, flush_fence, fence);
559    if (!fence)
560       return false;
561 
562    idle = screen->fence_finish(screen, pipe, fence, timeout_ms * 1000000);
563    screen->fence_reference(screen, &fence, NULL);
564    if (!idle)
565       fprintf(stderr, "dd: GPU hang detected!\n");
566    return !idle;
567 }
568 
569 static void
dd_flush_and_handle_hang(struct dd_context * dctx,struct pipe_fence_handle ** fence,unsigned flags,const char * cause)570 dd_flush_and_handle_hang(struct dd_context *dctx,
571                          struct pipe_fence_handle **fence, unsigned flags,
572                          const char *cause)
573 {
574    if (dd_flush_and_check_hang(dctx, fence, flags)) {
575       FILE *f = dd_get_file_stream(dd_screen(dctx->base.screen),
576                                    dctx->draw_state.apitrace_call_number);
577 
578       if (f) {
579          fprintf(f, "dd: %s.\n", cause);
580          dd_dump_driver_state(dctx, f,
581                               PIPE_DUMP_DEVICE_STATUS_REGISTERS |
582                               PIPE_DUMP_CURRENT_STATES |
583                               PIPE_DUMP_CURRENT_SHADERS |
584                               PIPE_DUMP_LAST_COMMAND_BUFFER);
585          dd_dump_dmesg(f);
586          dd_close_file_stream(f);
587       }
588 
589       /* Terminate the process to prevent future hangs. */
590       dd_kill_process();
591    }
592 }
593 
594 static void
dd_unreference_copy_of_call(struct dd_call * dst)595 dd_unreference_copy_of_call(struct dd_call *dst)
596 {
597    switch (dst->type) {
598    case CALL_DRAW_VBO:
599       pipe_so_target_reference(&dst->info.draw_vbo.count_from_stream_output, NULL);
600       pipe_resource_reference(&dst->info.draw_vbo.indirect, NULL);
601       pipe_resource_reference(&dst->info.draw_vbo.indirect_params, NULL);
602       break;
603    case CALL_LAUNCH_GRID:
604       pipe_resource_reference(&dst->info.launch_grid.indirect, NULL);
605       break;
606    case CALL_RESOURCE_COPY_REGION:
607       pipe_resource_reference(&dst->info.resource_copy_region.dst, NULL);
608       pipe_resource_reference(&dst->info.resource_copy_region.src, NULL);
609       break;
610    case CALL_BLIT:
611       pipe_resource_reference(&dst->info.blit.dst.resource, NULL);
612       pipe_resource_reference(&dst->info.blit.src.resource, NULL);
613       break;
614    case CALL_FLUSH_RESOURCE:
615       pipe_resource_reference(&dst->info.flush_resource, NULL);
616       break;
617    case CALL_CLEAR:
618       break;
619    case CALL_CLEAR_BUFFER:
620       pipe_resource_reference(&dst->info.clear_buffer.res, NULL);
621       break;
622    case CALL_CLEAR_RENDER_TARGET:
623       break;
624    case CALL_CLEAR_DEPTH_STENCIL:
625       break;
626    case CALL_GENERATE_MIPMAP:
627       pipe_resource_reference(&dst->info.generate_mipmap.res, NULL);
628       break;
629    }
630 }
631 
632 static void
dd_copy_call(struct dd_call * dst,struct dd_call * src)633 dd_copy_call(struct dd_call *dst, struct dd_call *src)
634 {
635    dst->type = src->type;
636 
637    switch (src->type) {
638    case CALL_DRAW_VBO:
639       pipe_so_target_reference(&dst->info.draw_vbo.count_from_stream_output,
640                                src->info.draw_vbo.count_from_stream_output);
641       pipe_resource_reference(&dst->info.draw_vbo.indirect,
642                               src->info.draw_vbo.indirect);
643       pipe_resource_reference(&dst->info.draw_vbo.indirect_params,
644                               src->info.draw_vbo.indirect_params);
645       dst->info.draw_vbo = src->info.draw_vbo;
646       break;
647    case CALL_LAUNCH_GRID:
648       pipe_resource_reference(&dst->info.launch_grid.indirect,
649                               src->info.launch_grid.indirect);
650       dst->info.launch_grid = src->info.launch_grid;
651       break;
652    case CALL_RESOURCE_COPY_REGION:
653       pipe_resource_reference(&dst->info.resource_copy_region.dst,
654                               src->info.resource_copy_region.dst);
655       pipe_resource_reference(&dst->info.resource_copy_region.src,
656                               src->info.resource_copy_region.src);
657       dst->info.resource_copy_region = src->info.resource_copy_region;
658       break;
659    case CALL_BLIT:
660       pipe_resource_reference(&dst->info.blit.dst.resource,
661                               src->info.blit.dst.resource);
662       pipe_resource_reference(&dst->info.blit.src.resource,
663                               src->info.blit.src.resource);
664       dst->info.blit = src->info.blit;
665       break;
666    case CALL_FLUSH_RESOURCE:
667       pipe_resource_reference(&dst->info.flush_resource,
668                               src->info.flush_resource);
669       break;
670    case CALL_CLEAR:
671       dst->info.clear = src->info.clear;
672       break;
673    case CALL_CLEAR_BUFFER:
674       pipe_resource_reference(&dst->info.clear_buffer.res,
675                               src->info.clear_buffer.res);
676       dst->info.clear_buffer = src->info.clear_buffer;
677       break;
678    case CALL_CLEAR_RENDER_TARGET:
679       break;
680    case CALL_CLEAR_DEPTH_STENCIL:
681       break;
682    case CALL_GENERATE_MIPMAP:
683       pipe_resource_reference(&dst->info.generate_mipmap.res,
684                               src->info.generate_mipmap.res);
685       dst->info.generate_mipmap = src->info.generate_mipmap;
686       break;
687    }
688 }
689 
690 static void
dd_init_copy_of_draw_state(struct dd_draw_state_copy * state)691 dd_init_copy_of_draw_state(struct dd_draw_state_copy *state)
692 {
693    unsigned i,j;
694 
695    /* Just clear pointers to gallium objects. Don't clear the whole structure,
696     * because it would kill performance with its size of 130 KB.
697     */
698    memset(&state->base.index_buffer, 0,
699           sizeof(state->base.index_buffer));
700    memset(state->base.vertex_buffers, 0,
701           sizeof(state->base.vertex_buffers));
702    memset(state->base.so_targets, 0,
703           sizeof(state->base.so_targets));
704    memset(state->base.constant_buffers, 0,
705           sizeof(state->base.constant_buffers));
706    memset(state->base.sampler_views, 0,
707           sizeof(state->base.sampler_views));
708    memset(state->base.shader_images, 0,
709           sizeof(state->base.shader_images));
710    memset(state->base.shader_buffers, 0,
711           sizeof(state->base.shader_buffers));
712    memset(&state->base.framebuffer_state, 0,
713           sizeof(state->base.framebuffer_state));
714 
715    memset(state->shaders, 0, sizeof(state->shaders));
716 
717    state->base.render_cond.query = &state->render_cond;
718 
719    for (i = 0; i < PIPE_SHADER_TYPES; i++) {
720       state->base.shaders[i] = &state->shaders[i];
721       for (j = 0; j < PIPE_MAX_SAMPLERS; j++)
722          state->base.sampler_states[i][j] = &state->sampler_states[i][j];
723    }
724 
725    state->base.velems = &state->velems;
726    state->base.rs = &state->rs;
727    state->base.dsa = &state->dsa;
728    state->base.blend = &state->blend;
729 }
730 
731 static void
dd_unreference_copy_of_draw_state(struct dd_draw_state_copy * state)732 dd_unreference_copy_of_draw_state(struct dd_draw_state_copy *state)
733 {
734    struct dd_draw_state *dst = &state->base;
735    unsigned i,j;
736 
737    util_set_index_buffer(&dst->index_buffer, NULL);
738 
739    for (i = 0; i < ARRAY_SIZE(dst->vertex_buffers); i++)
740       pipe_resource_reference(&dst->vertex_buffers[i].buffer, NULL);
741    for (i = 0; i < ARRAY_SIZE(dst->so_targets); i++)
742       pipe_so_target_reference(&dst->so_targets[i], NULL);
743 
744    for (i = 0; i < PIPE_SHADER_TYPES; i++) {
745       if (dst->shaders[i])
746          tgsi_free_tokens(dst->shaders[i]->state.shader.tokens);
747 
748       for (j = 0; j < PIPE_MAX_CONSTANT_BUFFERS; j++)
749          pipe_resource_reference(&dst->constant_buffers[i][j].buffer, NULL);
750       for (j = 0; j < PIPE_MAX_SAMPLERS; j++)
751          pipe_sampler_view_reference(&dst->sampler_views[i][j], NULL);
752       for (j = 0; j < PIPE_MAX_SHADER_IMAGES; j++)
753          pipe_resource_reference(&dst->shader_images[i][j].resource, NULL);
754       for (j = 0; j < PIPE_MAX_SHADER_BUFFERS; j++)
755          pipe_resource_reference(&dst->shader_buffers[i][j].buffer, NULL);
756    }
757 
758    util_unreference_framebuffer_state(&dst->framebuffer_state);
759 }
760 
761 static void
dd_copy_draw_state(struct dd_draw_state * dst,struct dd_draw_state * src)762 dd_copy_draw_state(struct dd_draw_state *dst, struct dd_draw_state *src)
763 {
764    unsigned i,j;
765 
766    if (src->render_cond.query) {
767       *dst->render_cond.query = *src->render_cond.query;
768       dst->render_cond.condition = src->render_cond.condition;
769       dst->render_cond.mode = src->render_cond.mode;
770    } else {
771       dst->render_cond.query = NULL;
772    }
773 
774    util_set_index_buffer(&dst->index_buffer, &src->index_buffer);
775 
776    for (i = 0; i < ARRAY_SIZE(src->vertex_buffers); i++) {
777       pipe_resource_reference(&dst->vertex_buffers[i].buffer,
778                               src->vertex_buffers[i].buffer);
779       memcpy(&dst->vertex_buffers[i], &src->vertex_buffers[i],
780              sizeof(src->vertex_buffers[i]));
781    }
782 
783    dst->num_so_targets = src->num_so_targets;
784    for (i = 0; i < ARRAY_SIZE(src->so_targets); i++)
785       pipe_so_target_reference(&dst->so_targets[i], src->so_targets[i]);
786    memcpy(dst->so_offsets, src->so_offsets, sizeof(src->so_offsets));
787 
788    for (i = 0; i < PIPE_SHADER_TYPES; i++) {
789       if (!src->shaders[i]) {
790          dst->shaders[i] = NULL;
791          continue;
792       }
793 
794       if (src->shaders[i]) {
795          dst->shaders[i]->state.shader = src->shaders[i]->state.shader;
796          dst->shaders[i]->state.shader.tokens =
797             tgsi_dup_tokens(src->shaders[i]->state.shader.tokens);
798       } else {
799          dst->shaders[i] = NULL;
800       }
801 
802       for (j = 0; j < PIPE_MAX_CONSTANT_BUFFERS; j++) {
803          pipe_resource_reference(&dst->constant_buffers[i][j].buffer,
804                                  src->constant_buffers[i][j].buffer);
805          memcpy(&dst->constant_buffers[i][j], &src->constant_buffers[i][j],
806                 sizeof(src->constant_buffers[i][j]));
807       }
808 
809       for (j = 0; j < PIPE_MAX_SAMPLERS; j++) {
810          pipe_sampler_view_reference(&dst->sampler_views[i][j],
811                                      src->sampler_views[i][j]);
812          if (src->sampler_states[i][j])
813             dst->sampler_states[i][j]->state.sampler =
814                src->sampler_states[i][j]->state.sampler;
815          else
816             dst->sampler_states[i][j] = NULL;
817       }
818 
819       for (j = 0; j < PIPE_MAX_SHADER_IMAGES; j++) {
820          pipe_resource_reference(&dst->shader_images[i][j].resource,
821                                  src->shader_images[i][j].resource);
822          memcpy(&dst->shader_images[i][j], &src->shader_images[i][j],
823                 sizeof(src->shader_images[i][j]));
824       }
825 
826       for (j = 0; j < PIPE_MAX_SHADER_BUFFERS; j++) {
827          pipe_resource_reference(&dst->shader_buffers[i][j].buffer,
828                                  src->shader_buffers[i][j].buffer);
829          memcpy(&dst->shader_buffers[i][j], &src->shader_buffers[i][j],
830                 sizeof(src->shader_buffers[i][j]));
831       }
832    }
833 
834    if (src->velems)
835       dst->velems->state.velems = src->velems->state.velems;
836    else
837       dst->velems = NULL;
838 
839    if (src->rs)
840       dst->rs->state.rs = src->rs->state.rs;
841    else
842       dst->rs = NULL;
843 
844    if (src->dsa)
845       dst->dsa->state.dsa = src->dsa->state.dsa;
846    else
847       dst->dsa = NULL;
848 
849    if (src->blend)
850       dst->blend->state.blend = src->blend->state.blend;
851    else
852       dst->blend = NULL;
853 
854    dst->blend_color = src->blend_color;
855    dst->stencil_ref = src->stencil_ref;
856    dst->sample_mask = src->sample_mask;
857    dst->min_samples = src->min_samples;
858    dst->clip_state = src->clip_state;
859    util_copy_framebuffer_state(&dst->framebuffer_state, &src->framebuffer_state);
860    memcpy(dst->scissors, src->scissors, sizeof(src->scissors));
861    memcpy(dst->viewports, src->viewports, sizeof(src->viewports));
862    memcpy(dst->tess_default_levels, src->tess_default_levels,
863           sizeof(src->tess_default_levels));
864    dst->apitrace_call_number = src->apitrace_call_number;
865 }
866 
867 static void
dd_free_record(struct dd_draw_record ** record)868 dd_free_record(struct dd_draw_record **record)
869 {
870    struct dd_draw_record *next = (*record)->next;
871 
872    dd_unreference_copy_of_call(&(*record)->call);
873    dd_unreference_copy_of_draw_state(&(*record)->draw_state);
874    FREE((*record)->driver_state_log);
875    FREE(*record);
876    *record = next;
877 }
878 
879 static void
dd_dump_record(struct dd_context * dctx,struct dd_draw_record * record,uint32_t hw_sequence_no,int64_t now)880 dd_dump_record(struct dd_context *dctx, struct dd_draw_record *record,
881                uint32_t hw_sequence_no, int64_t now)
882 {
883    FILE *f = dd_get_file_stream(dd_screen(dctx->base.screen),
884                                 record->draw_state.base.apitrace_call_number);
885    if (!f)
886       return;
887 
888    fprintf(f, "Draw call sequence # = %u\n", record->sequence_no);
889    fprintf(f, "HW reached sequence # = %u\n", hw_sequence_no);
890    fprintf(f, "Elapsed time = %"PRIi64" ms\n\n",
891            (now - record->timestamp) / 1000);
892 
893    dd_dump_call(f, &record->draw_state.base, &record->call);
894    fprintf(f, "%s\n", record->driver_state_log);
895 
896    dctx->pipe->dump_debug_state(dctx->pipe, f,
897                                 PIPE_DUMP_DEVICE_STATUS_REGISTERS);
898    dd_dump_dmesg(f);
899    fclose(f);
900 }
901 
PIPE_THREAD_ROUTINE(dd_thread_pipelined_hang_detect,input)902 PIPE_THREAD_ROUTINE(dd_thread_pipelined_hang_detect, input)
903 {
904    struct dd_context *dctx = (struct dd_context *)input;
905    struct dd_screen *dscreen = dd_screen(dctx->base.screen);
906 
907    pipe_mutex_lock(dctx->mutex);
908 
909    while (!dctx->kill_thread) {
910       struct dd_draw_record **record = &dctx->records;
911 
912       /* Loop over all records. */
913       while (*record) {
914          int64_t now;
915 
916          /* If the fence has been signalled, release the record and all older
917           * records.
918           */
919          if (*dctx->mapped_fence >= (*record)->sequence_no) {
920             while (*record)
921                dd_free_record(record);
922             break;
923          }
924 
925          /* The fence hasn't been signalled. Check the timeout. */
926          now = os_time_get();
927          if (os_time_timeout((*record)->timestamp,
928                              (*record)->timestamp + dscreen->timeout_ms * 1000,
929                              now)) {
930             fprintf(stderr, "GPU hang detected.\n");
931 
932             /* Get the oldest unsignalled draw call. */
933             while ((*record)->next &&
934                    *dctx->mapped_fence < (*record)->next->sequence_no)
935                record = &(*record)->next;
936 
937             dd_dump_record(dctx, *record, *dctx->mapped_fence, now);
938             dd_kill_process();
939          }
940 
941          record = &(*record)->next;
942       }
943 
944       /* Unlock and sleep before starting all over again. */
945       pipe_mutex_unlock(dctx->mutex);
946       os_time_sleep(10000); /* 10 ms */
947       pipe_mutex_lock(dctx->mutex);
948    }
949 
950    /* Thread termination. */
951    while (dctx->records)
952       dd_free_record(&dctx->records);
953 
954    pipe_mutex_unlock(dctx->mutex);
955    return 0;
956 }
957 
958 static char *
dd_get_driver_shader_log(struct dd_context * dctx)959 dd_get_driver_shader_log(struct dd_context *dctx)
960 {
961 #if defined(PIPE_OS_LINUX)
962    FILE *f;
963    char *buf;
964    int written_bytes;
965 
966    if (!dctx->max_log_buffer_size)
967       dctx->max_log_buffer_size = 16 * 1024;
968 
969    /* Keep increasing the buffer size until there is enough space.
970     *
971     * open_memstream can resize automatically, but it's VERY SLOW.
972     * fmemopen is much faster.
973     */
974    while (1) {
975       buf = malloc(dctx->max_log_buffer_size);
976       buf[0] = 0;
977 
978       f = fmemopen(buf, dctx->max_log_buffer_size, "a");
979       if (!f) {
980          free(buf);
981          return NULL;
982       }
983 
984       dd_dump_driver_state(dctx, f, PIPE_DUMP_CURRENT_SHADERS);
985       written_bytes = ftell(f);
986       fclose(f);
987 
988       /* Return if the backing buffer is large enough. */
989       if (written_bytes < dctx->max_log_buffer_size - 1)
990          break;
991 
992       /* Try again. */
993       free(buf);
994       dctx->max_log_buffer_size *= 2;
995    }
996 
997    return buf;
998 #else
999    /* Return an empty string. */
1000    return (char*)calloc(1, 4);
1001 #endif
1002 }
1003 
1004 static void
dd_pipelined_process_draw(struct dd_context * dctx,struct dd_call * call)1005 dd_pipelined_process_draw(struct dd_context *dctx, struct dd_call *call)
1006 {
1007    struct pipe_context *pipe = dctx->pipe;
1008    struct dd_draw_record *record;
1009    char *log;
1010 
1011    /* Make a record of the draw call. */
1012    record = MALLOC_STRUCT(dd_draw_record);
1013    if (!record)
1014       return;
1015 
1016    /* Create the log. */
1017    log = dd_get_driver_shader_log(dctx);
1018    if (!log) {
1019       FREE(record);
1020       return;
1021    }
1022 
1023    /* Update the fence with the GPU.
1024     *
1025     * radeonsi/clear_buffer waits in the command processor until shaders are
1026     * idle before writing to memory. That's a necessary condition for isolating
1027     * draw calls.
1028     */
1029    dctx->sequence_no++;
1030    pipe->clear_buffer(pipe, dctx->fence, 0, 4, &dctx->sequence_no, 4);
1031 
1032    /* Initialize the record. */
1033    record->timestamp = os_time_get();
1034    record->sequence_no = dctx->sequence_no;
1035    record->driver_state_log = log;
1036 
1037    memset(&record->call, 0, sizeof(record->call));
1038    dd_copy_call(&record->call, call);
1039 
1040    dd_init_copy_of_draw_state(&record->draw_state);
1041    dd_copy_draw_state(&record->draw_state.base, &dctx->draw_state);
1042 
1043    /* Add the record to the list. */
1044    pipe_mutex_lock(dctx->mutex);
1045    record->next = dctx->records;
1046    dctx->records = record;
1047    pipe_mutex_unlock(dctx->mutex);
1048 }
1049 
1050 static void
dd_context_flush(struct pipe_context * _pipe,struct pipe_fence_handle ** fence,unsigned flags)1051 dd_context_flush(struct pipe_context *_pipe,
1052                  struct pipe_fence_handle **fence, unsigned flags)
1053 {
1054    struct dd_context *dctx = dd_context(_pipe);
1055    struct pipe_context *pipe = dctx->pipe;
1056 
1057    switch (dd_screen(dctx->base.screen)->mode) {
1058    case DD_DETECT_HANGS:
1059       dd_flush_and_handle_hang(dctx, fence, flags,
1060                                "GPU hang detected in pipe->flush()");
1061       break;
1062    case DD_DETECT_HANGS_PIPELINED: /* nothing to do here */
1063    case DD_DUMP_ALL_CALLS:
1064    case DD_DUMP_APITRACE_CALL:
1065       pipe->flush(pipe, fence, flags);
1066       break;
1067    default:
1068       assert(0);
1069    }
1070 }
1071 
1072 static void
dd_before_draw(struct dd_context * dctx)1073 dd_before_draw(struct dd_context *dctx)
1074 {
1075    struct dd_screen *dscreen = dd_screen(dctx->base.screen);
1076 
1077    if (dscreen->mode == DD_DETECT_HANGS &&
1078        !dscreen->no_flush &&
1079        dctx->num_draw_calls >= dscreen->skip_count)
1080       dd_flush_and_handle_hang(dctx, NULL, 0,
1081                                "GPU hang most likely caused by internal "
1082                                "driver commands");
1083 }
1084 
1085 static void
dd_after_draw(struct dd_context * dctx,struct dd_call * call)1086 dd_after_draw(struct dd_context *dctx, struct dd_call *call)
1087 {
1088    struct dd_screen *dscreen = dd_screen(dctx->base.screen);
1089    struct pipe_context *pipe = dctx->pipe;
1090 
1091    if (dctx->num_draw_calls >= dscreen->skip_count) {
1092       switch (dscreen->mode) {
1093       case DD_DETECT_HANGS:
1094          if (!dscreen->no_flush &&
1095             dd_flush_and_check_hang(dctx, NULL, 0)) {
1096             dd_write_report(dctx, call,
1097                          PIPE_DUMP_DEVICE_STATUS_REGISTERS |
1098                          PIPE_DUMP_CURRENT_STATES |
1099                          PIPE_DUMP_CURRENT_SHADERS |
1100                          PIPE_DUMP_LAST_COMMAND_BUFFER,
1101                          true);
1102 
1103             /* Terminate the process to prevent future hangs. */
1104             dd_kill_process();
1105          }
1106          break;
1107       case DD_DETECT_HANGS_PIPELINED:
1108          dd_pipelined_process_draw(dctx, call);
1109          break;
1110       case DD_DUMP_ALL_CALLS:
1111          if (!dscreen->no_flush)
1112             pipe->flush(pipe, NULL, 0);
1113          dd_write_report(dctx, call,
1114                          PIPE_DUMP_CURRENT_STATES |
1115                          PIPE_DUMP_CURRENT_SHADERS |
1116                          PIPE_DUMP_LAST_COMMAND_BUFFER,
1117                          false);
1118          break;
1119       case DD_DUMP_APITRACE_CALL:
1120          if (dscreen->apitrace_dump_call ==
1121              dctx->draw_state.apitrace_call_number) {
1122             dd_write_report(dctx, call,
1123                             PIPE_DUMP_CURRENT_STATES |
1124                             PIPE_DUMP_CURRENT_SHADERS,
1125                             false);
1126             /* No need to continue. */
1127             exit(0);
1128          }
1129          break;
1130       default:
1131          assert(0);
1132       }
1133    }
1134 
1135    ++dctx->num_draw_calls;
1136    if (dscreen->skip_count && dctx->num_draw_calls % 10000 == 0)
1137       fprintf(stderr, "Gallium debugger reached %u draw calls.\n",
1138               dctx->num_draw_calls);
1139 }
1140 
1141 static void
dd_context_draw_vbo(struct pipe_context * _pipe,const struct pipe_draw_info * info)1142 dd_context_draw_vbo(struct pipe_context *_pipe,
1143                     const struct pipe_draw_info *info)
1144 {
1145    struct dd_context *dctx = dd_context(_pipe);
1146    struct pipe_context *pipe = dctx->pipe;
1147    struct dd_call call;
1148 
1149    call.type = CALL_DRAW_VBO;
1150    call.info.draw_vbo = *info;
1151 
1152    dd_before_draw(dctx);
1153    pipe->draw_vbo(pipe, info);
1154    dd_after_draw(dctx, &call);
1155 }
1156 
1157 static void
dd_context_launch_grid(struct pipe_context * _pipe,const struct pipe_grid_info * info)1158 dd_context_launch_grid(struct pipe_context *_pipe,
1159                        const struct pipe_grid_info *info)
1160 {
1161    struct dd_context *dctx = dd_context(_pipe);
1162    struct pipe_context *pipe = dctx->pipe;
1163    struct dd_call call;
1164 
1165    call.type = CALL_LAUNCH_GRID;
1166    call.info.launch_grid = *info;
1167 
1168    dd_before_draw(dctx);
1169    pipe->launch_grid(pipe, info);
1170    dd_after_draw(dctx, &call);
1171 }
1172 
1173 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)1174 dd_context_resource_copy_region(struct pipe_context *_pipe,
1175                                 struct pipe_resource *dst, unsigned dst_level,
1176                                 unsigned dstx, unsigned dsty, unsigned dstz,
1177                                 struct pipe_resource *src, unsigned src_level,
1178                                 const struct pipe_box *src_box)
1179 {
1180    struct dd_context *dctx = dd_context(_pipe);
1181    struct pipe_context *pipe = dctx->pipe;
1182    struct dd_call call;
1183 
1184    call.type = CALL_RESOURCE_COPY_REGION;
1185    call.info.resource_copy_region.dst = dst;
1186    call.info.resource_copy_region.dst_level = dst_level;
1187    call.info.resource_copy_region.dstx = dstx;
1188    call.info.resource_copy_region.dsty = dsty;
1189    call.info.resource_copy_region.dstz = dstz;
1190    call.info.resource_copy_region.src = src;
1191    call.info.resource_copy_region.src_level = src_level;
1192    call.info.resource_copy_region.src_box = *src_box;
1193 
1194    dd_before_draw(dctx);
1195    pipe->resource_copy_region(pipe,
1196                               dst, dst_level, dstx, dsty, dstz,
1197                               src, src_level, src_box);
1198    dd_after_draw(dctx, &call);
1199 }
1200 
1201 static void
dd_context_blit(struct pipe_context * _pipe,const struct pipe_blit_info * info)1202 dd_context_blit(struct pipe_context *_pipe, const struct pipe_blit_info *info)
1203 {
1204    struct dd_context *dctx = dd_context(_pipe);
1205    struct pipe_context *pipe = dctx->pipe;
1206    struct dd_call call;
1207 
1208    call.type = CALL_BLIT;
1209    call.info.blit = *info;
1210 
1211    dd_before_draw(dctx);
1212    pipe->blit(pipe, info);
1213    dd_after_draw(dctx, &call);
1214 }
1215 
1216 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)1217 dd_context_generate_mipmap(struct pipe_context *_pipe,
1218                            struct pipe_resource *res,
1219                            enum pipe_format format,
1220                            unsigned base_level,
1221                            unsigned last_level,
1222                            unsigned first_layer,
1223                            unsigned last_layer)
1224 {
1225    struct dd_context *dctx = dd_context(_pipe);
1226    struct pipe_context *pipe = dctx->pipe;
1227    struct dd_call call;
1228    boolean result;
1229 
1230    call.type = CALL_GENERATE_MIPMAP;
1231    call.info.generate_mipmap.res = res;
1232    call.info.generate_mipmap.format = format;
1233    call.info.generate_mipmap.base_level = base_level;
1234    call.info.generate_mipmap.last_level = last_level;
1235    call.info.generate_mipmap.first_layer = first_layer;
1236    call.info.generate_mipmap.last_layer = last_layer;
1237 
1238    dd_before_draw(dctx);
1239    result = pipe->generate_mipmap(pipe, res, format, base_level, last_level,
1240                                   first_layer, last_layer);
1241    dd_after_draw(dctx, &call);
1242    return result;
1243 }
1244 
1245 static void
dd_context_flush_resource(struct pipe_context * _pipe,struct pipe_resource * resource)1246 dd_context_flush_resource(struct pipe_context *_pipe,
1247                           struct pipe_resource *resource)
1248 {
1249    struct dd_context *dctx = dd_context(_pipe);
1250    struct pipe_context *pipe = dctx->pipe;
1251    struct dd_call call;
1252 
1253    call.type = CALL_FLUSH_RESOURCE;
1254    call.info.flush_resource = resource;
1255 
1256    dd_before_draw(dctx);
1257    pipe->flush_resource(pipe, resource);
1258    dd_after_draw(dctx, &call);
1259 }
1260 
1261 static void
dd_context_clear(struct pipe_context * _pipe,unsigned buffers,const union pipe_color_union * color,double depth,unsigned stencil)1262 dd_context_clear(struct pipe_context *_pipe, unsigned buffers,
1263                  const union pipe_color_union *color, double depth,
1264                  unsigned stencil)
1265 {
1266    struct dd_context *dctx = dd_context(_pipe);
1267    struct pipe_context *pipe = dctx->pipe;
1268    struct dd_call call;
1269 
1270    call.type = CALL_CLEAR;
1271    call.info.clear.buffers = buffers;
1272    call.info.clear.color = *color;
1273    call.info.clear.depth = depth;
1274    call.info.clear.stencil = stencil;
1275 
1276    dd_before_draw(dctx);
1277    pipe->clear(pipe, buffers, color, depth, stencil);
1278    dd_after_draw(dctx, &call);
1279 }
1280 
1281 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)1282 dd_context_clear_render_target(struct pipe_context *_pipe,
1283                                struct pipe_surface *dst,
1284                                const union pipe_color_union *color,
1285                                unsigned dstx, unsigned dsty,
1286                                unsigned width, unsigned height,
1287                                bool render_condition_enabled)
1288 {
1289    struct dd_context *dctx = dd_context(_pipe);
1290    struct pipe_context *pipe = dctx->pipe;
1291    struct dd_call call;
1292 
1293    call.type = CALL_CLEAR_RENDER_TARGET;
1294 
1295    dd_before_draw(dctx);
1296    pipe->clear_render_target(pipe, dst, color, dstx, dsty, width, height,
1297                              render_condition_enabled);
1298    dd_after_draw(dctx, &call);
1299 }
1300 
1301 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)1302 dd_context_clear_depth_stencil(struct pipe_context *_pipe,
1303                                struct pipe_surface *dst, unsigned clear_flags,
1304                                double depth, unsigned stencil, unsigned dstx,
1305                                unsigned dsty, unsigned width, unsigned height,
1306                                bool render_condition_enabled)
1307 {
1308    struct dd_context *dctx = dd_context(_pipe);
1309    struct pipe_context *pipe = dctx->pipe;
1310    struct dd_call call;
1311 
1312    call.type = CALL_CLEAR_DEPTH_STENCIL;
1313 
1314    dd_before_draw(dctx);
1315    pipe->clear_depth_stencil(pipe, dst, clear_flags, depth, stencil,
1316                              dstx, dsty, width, height,
1317                              render_condition_enabled);
1318    dd_after_draw(dctx, &call);
1319 }
1320 
1321 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)1322 dd_context_clear_buffer(struct pipe_context *_pipe, struct pipe_resource *res,
1323                         unsigned offset, unsigned size,
1324                         const void *clear_value, int clear_value_size)
1325 {
1326    struct dd_context *dctx = dd_context(_pipe);
1327    struct pipe_context *pipe = dctx->pipe;
1328    struct dd_call call;
1329 
1330    call.type = CALL_CLEAR_BUFFER;
1331    call.info.clear_buffer.res = res;
1332    call.info.clear_buffer.offset = offset;
1333    call.info.clear_buffer.size = size;
1334    call.info.clear_buffer.clear_value = clear_value;
1335    call.info.clear_buffer.clear_value_size = clear_value_size;
1336 
1337    dd_before_draw(dctx);
1338    pipe->clear_buffer(pipe, res, offset, size, clear_value, clear_value_size);
1339    dd_after_draw(dctx, &call);
1340 }
1341 
1342 void
dd_init_draw_functions(struct dd_context * dctx)1343 dd_init_draw_functions(struct dd_context *dctx)
1344 {
1345    CTX_INIT(flush);
1346    CTX_INIT(draw_vbo);
1347    CTX_INIT(launch_grid);
1348    CTX_INIT(resource_copy_region);
1349    CTX_INIT(blit);
1350    CTX_INIT(clear);
1351    CTX_INIT(clear_render_target);
1352    CTX_INIT(clear_depth_stencil);
1353    CTX_INIT(clear_buffer);
1354    CTX_INIT(flush_resource);
1355    CTX_INIT(generate_mipmap);
1356 }
1357