gallium: add a pipe_context parameter to fence_finish
[mesa.git] / src / gallium / drivers / ddebug / dd_draw.c
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 *
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
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
81 dd_close_file_stream(FILE *f)
82 {
83 fclose(f);
84 }
85
86 static unsigned
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
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
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
146 util_dump_uint(FILE *f, unsigned i)
147 {
148 fprintf(f, "%u", i);
149 }
150
151 static void
152 util_dump_hex(FILE *f, unsigned i)
153 {
154 fprintf(f, "0x%x", i);
155 }
156
157 static void
158 util_dump_double(FILE *f, double d)
159 {
160 fprintf(f, "%f", d);
161 }
162
163 static void
164 util_dump_format(FILE *f, enum pipe_format format)
165 {
166 fprintf(f, "%s", util_format_name(format));
167 }
168
169 static void
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
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
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
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 /* TODO: print shader images */
317 /* TODO: print shader buffers */
318
319 fprintf(f, COLOR_SHADER "end shader: %s" COLOR_RESET "\n\n", shader_str[sh]);
320 }
321
322 if (dstate->dsa)
323 DUMP(depth_stencil_alpha_state, &dstate->dsa->state.dsa);
324 DUMP(stencil_ref, &dstate->stencil_ref);
325
326 if (dstate->blend)
327 DUMP(blend_state, &dstate->blend->state.blend);
328 DUMP(blend_color, &dstate->blend_color);
329
330 print_named_value(f, "min_samples", dstate->min_samples);
331 print_named_xvalue(f, "sample_mask", dstate->sample_mask);
332 fprintf(f, "\n");
333
334 DUMP(framebuffer_state, &dstate->framebuffer_state);
335 for (i = 0; i < dstate->framebuffer_state.nr_cbufs; i++)
336 if (dstate->framebuffer_state.cbufs[i]) {
337 fprintf(f, " " COLOR_STATE "cbufs[%i]:" COLOR_RESET "\n ", i);
338 DUMP(surface, dstate->framebuffer_state.cbufs[i]);
339 fprintf(f, " ");
340 DUMP(resource, dstate->framebuffer_state.cbufs[i]->texture);
341 }
342 if (dstate->framebuffer_state.zsbuf) {
343 fprintf(f, " " COLOR_STATE "zsbuf:" COLOR_RESET "\n ");
344 DUMP(surface, dstate->framebuffer_state.zsbuf);
345 fprintf(f, " ");
346 DUMP(resource, dstate->framebuffer_state.zsbuf->texture);
347 }
348 fprintf(f, "\n");
349 }
350
351 static void
352 dd_dump_launch_grid(struct dd_draw_state *dstate, struct pipe_grid_info *info, FILE *f)
353 {
354 fprintf(f, "%s:\n", __func__+8);
355 /* TODO */
356 }
357
358 static void
359 dd_dump_resource_copy_region(struct dd_draw_state *dstate,
360 struct call_resource_copy_region *info,
361 FILE *f)
362 {
363 fprintf(f, "%s:\n", __func__+8);
364 DUMP_M(resource, info, dst);
365 DUMP_M(uint, info, dst_level);
366 DUMP_M(uint, info, dstx);
367 DUMP_M(uint, info, dsty);
368 DUMP_M(uint, info, dstz);
369 DUMP_M(resource, info, src);
370 DUMP_M(uint, info, src_level);
371 DUMP_M_ADDR(box, info, src_box);
372 }
373
374 static void
375 dd_dump_blit(struct dd_draw_state *dstate, struct pipe_blit_info *info, FILE *f)
376 {
377 fprintf(f, "%s:\n", __func__+8);
378 DUMP_M(resource, info, dst.resource);
379 DUMP_M(uint, info, dst.level);
380 DUMP_M_ADDR(box, info, dst.box);
381 DUMP_M(format, info, dst.format);
382
383 DUMP_M(resource, info, src.resource);
384 DUMP_M(uint, info, src.level);
385 DUMP_M_ADDR(box, info, src.box);
386 DUMP_M(format, info, src.format);
387
388 DUMP_M(hex, info, mask);
389 DUMP_M(uint, info, filter);
390 DUMP_M(uint, info, scissor_enable);
391 DUMP_M_ADDR(scissor_state, info, scissor);
392 DUMP_M(uint, info, render_condition_enable);
393
394 if (info->render_condition_enable)
395 dd_dump_render_condition(dstate, f);
396 }
397
398 static void
399 dd_dump_generate_mipmap(struct dd_draw_state *dstate, FILE *f)
400 {
401 fprintf(f, "%s:\n", __func__+8);
402 /* TODO */
403 }
404
405 static void
406 dd_dump_flush_resource(struct dd_draw_state *dstate, struct pipe_resource *res,
407 FILE *f)
408 {
409 fprintf(f, "%s:\n", __func__+8);
410 DUMP(resource, res);
411 }
412
413 static void
414 dd_dump_clear(struct dd_draw_state *dstate, struct call_clear *info, FILE *f)
415 {
416 fprintf(f, "%s:\n", __func__+8);
417 DUMP_M(uint, info, buffers);
418 DUMP_M_ADDR(color_union, info, color);
419 DUMP_M(double, info, depth);
420 DUMP_M(hex, info, stencil);
421 }
422
423 static void
424 dd_dump_clear_buffer(struct dd_draw_state *dstate, struct call_clear_buffer *info,
425 FILE *f)
426 {
427 int i;
428 const char *value = (const char*)info->clear_value;
429
430 fprintf(f, "%s:\n", __func__+8);
431 DUMP_M(resource, info, res);
432 DUMP_M(uint, info, offset);
433 DUMP_M(uint, info, size);
434 DUMP_M(uint, info, clear_value_size);
435
436 fprintf(f, " clear_value:");
437 for (i = 0; i < info->clear_value_size; i++)
438 fprintf(f, " %02x", value[i]);
439 fprintf(f, "\n");
440 }
441
442 static void
443 dd_dump_clear_render_target(struct dd_draw_state *dstate, FILE *f)
444 {
445 fprintf(f, "%s:\n", __func__+8);
446 /* TODO */
447 }
448
449 static void
450 dd_dump_clear_depth_stencil(struct dd_draw_state *dstate, FILE *f)
451 {
452 fprintf(f, "%s:\n", __func__+8);
453 /* TODO */
454 }
455
456 static void
457 dd_dump_driver_state(struct dd_context *dctx, FILE *f, unsigned flags)
458 {
459 if (dctx->pipe->dump_debug_state) {
460 fprintf(f,"\n\n**************************************************"
461 "***************************\n");
462 fprintf(f, "Driver-specific state:\n\n");
463 dctx->pipe->dump_debug_state(dctx->pipe, f, flags);
464 }
465 }
466
467 static void
468 dd_dump_call(FILE *f, struct dd_draw_state *state, struct dd_call *call)
469 {
470 switch (call->type) {
471 case CALL_DRAW_VBO:
472 dd_dump_draw_vbo(state, &call->info.draw_vbo, f);
473 break;
474 case CALL_LAUNCH_GRID:
475 dd_dump_launch_grid(state, &call->info.launch_grid, f);
476 break;
477 case CALL_RESOURCE_COPY_REGION:
478 dd_dump_resource_copy_region(state,
479 &call->info.resource_copy_region, f);
480 break;
481 case CALL_BLIT:
482 dd_dump_blit(state, &call->info.blit, f);
483 break;
484 case CALL_FLUSH_RESOURCE:
485 dd_dump_flush_resource(state, call->info.flush_resource, f);
486 break;
487 case CALL_CLEAR:
488 dd_dump_clear(state, &call->info.clear, f);
489 break;
490 case CALL_CLEAR_BUFFER:
491 dd_dump_clear_buffer(state, &call->info.clear_buffer, f);
492 break;
493 case CALL_CLEAR_RENDER_TARGET:
494 dd_dump_clear_render_target(state, f);
495 break;
496 case CALL_CLEAR_DEPTH_STENCIL:
497 dd_dump_clear_depth_stencil(state, f);
498 break;
499 case CALL_GENERATE_MIPMAP:
500 dd_dump_generate_mipmap(state, f);
501 break;
502 }
503 }
504
505 static void
506 dd_write_report(struct dd_context *dctx, struct dd_call *call, unsigned flags,
507 bool dump_dmesg)
508 {
509 FILE *f = dd_get_file_stream(dd_screen(dctx->base.screen),
510 dctx->draw_state.apitrace_call_number);
511
512 if (!f)
513 return;
514
515 dd_dump_call(f, &dctx->draw_state, call);
516 dd_dump_driver_state(dctx, f, flags);
517 if (dump_dmesg)
518 dd_dump_dmesg(f);
519 dd_close_file_stream(f);
520 }
521
522 static void
523 dd_kill_process(void)
524 {
525 sync();
526 fprintf(stderr, "dd: Aborting the process...\n");
527 fflush(stdout);
528 fflush(stderr);
529 exit(1);
530 }
531
532 static bool
533 dd_flush_and_check_hang(struct dd_context *dctx,
534 struct pipe_fence_handle **flush_fence,
535 unsigned flush_flags)
536 {
537 struct pipe_fence_handle *fence = NULL;
538 struct pipe_context *pipe = dctx->pipe;
539 struct pipe_screen *screen = pipe->screen;
540 uint64_t timeout_ms = dd_screen(dctx->base.screen)->timeout_ms;
541 bool idle;
542
543 assert(timeout_ms > 0);
544
545 pipe->flush(pipe, &fence, flush_flags);
546 if (flush_fence)
547 screen->fence_reference(screen, flush_fence, fence);
548 if (!fence)
549 return false;
550
551 idle = screen->fence_finish(screen, NULL, fence, timeout_ms * 1000000);
552 screen->fence_reference(screen, &fence, NULL);
553 if (!idle)
554 fprintf(stderr, "dd: GPU hang detected!\n");
555 return !idle;
556 }
557
558 static void
559 dd_flush_and_handle_hang(struct dd_context *dctx,
560 struct pipe_fence_handle **fence, unsigned flags,
561 const char *cause)
562 {
563 if (dd_flush_and_check_hang(dctx, fence, flags)) {
564 FILE *f = dd_get_file_stream(dd_screen(dctx->base.screen),
565 dctx->draw_state.apitrace_call_number);
566
567 if (f) {
568 fprintf(f, "dd: %s.\n", cause);
569 dd_dump_driver_state(dctx, f,
570 PIPE_DUMP_DEVICE_STATUS_REGISTERS |
571 PIPE_DUMP_CURRENT_STATES |
572 PIPE_DUMP_CURRENT_SHADERS |
573 PIPE_DUMP_LAST_COMMAND_BUFFER);
574 dd_dump_dmesg(f);
575 dd_close_file_stream(f);
576 }
577
578 /* Terminate the process to prevent future hangs. */
579 dd_kill_process();
580 }
581 }
582
583 static void
584 dd_unreference_copy_of_call(struct dd_call *dst)
585 {
586 switch (dst->type) {
587 case CALL_DRAW_VBO:
588 pipe_so_target_reference(&dst->info.draw_vbo.count_from_stream_output, NULL);
589 pipe_resource_reference(&dst->info.draw_vbo.indirect, NULL);
590 pipe_resource_reference(&dst->info.draw_vbo.indirect_params, NULL);
591 break;
592 case CALL_LAUNCH_GRID:
593 pipe_resource_reference(&dst->info.launch_grid.indirect, NULL);
594 break;
595 case CALL_RESOURCE_COPY_REGION:
596 pipe_resource_reference(&dst->info.resource_copy_region.dst, NULL);
597 pipe_resource_reference(&dst->info.resource_copy_region.src, NULL);
598 break;
599 case CALL_BLIT:
600 pipe_resource_reference(&dst->info.blit.dst.resource, NULL);
601 pipe_resource_reference(&dst->info.blit.src.resource, NULL);
602 break;
603 case CALL_FLUSH_RESOURCE:
604 pipe_resource_reference(&dst->info.flush_resource, NULL);
605 break;
606 case CALL_CLEAR:
607 break;
608 case CALL_CLEAR_BUFFER:
609 pipe_resource_reference(&dst->info.clear_buffer.res, NULL);
610 break;
611 case CALL_CLEAR_RENDER_TARGET:
612 break;
613 case CALL_CLEAR_DEPTH_STENCIL:
614 break;
615 case CALL_GENERATE_MIPMAP:
616 pipe_resource_reference(&dst->info.generate_mipmap.res, NULL);
617 break;
618 }
619 }
620
621 static void
622 dd_copy_call(struct dd_call *dst, struct dd_call *src)
623 {
624 dst->type = src->type;
625
626 switch (src->type) {
627 case CALL_DRAW_VBO:
628 pipe_so_target_reference(&dst->info.draw_vbo.count_from_stream_output,
629 src->info.draw_vbo.count_from_stream_output);
630 pipe_resource_reference(&dst->info.draw_vbo.indirect,
631 src->info.draw_vbo.indirect);
632 pipe_resource_reference(&dst->info.draw_vbo.indirect_params,
633 src->info.draw_vbo.indirect_params);
634 dst->info.draw_vbo = src->info.draw_vbo;
635 break;
636 case CALL_LAUNCH_GRID:
637 pipe_resource_reference(&dst->info.launch_grid.indirect,
638 src->info.launch_grid.indirect);
639 dst->info.launch_grid = src->info.launch_grid;
640 break;
641 case CALL_RESOURCE_COPY_REGION:
642 pipe_resource_reference(&dst->info.resource_copy_region.dst,
643 src->info.resource_copy_region.dst);
644 pipe_resource_reference(&dst->info.resource_copy_region.src,
645 src->info.resource_copy_region.src);
646 dst->info.resource_copy_region = src->info.resource_copy_region;
647 break;
648 case CALL_BLIT:
649 pipe_resource_reference(&dst->info.blit.dst.resource,
650 src->info.blit.dst.resource);
651 pipe_resource_reference(&dst->info.blit.src.resource,
652 src->info.blit.src.resource);
653 dst->info.blit = src->info.blit;
654 break;
655 case CALL_FLUSH_RESOURCE:
656 pipe_resource_reference(&dst->info.flush_resource,
657 src->info.flush_resource);
658 break;
659 case CALL_CLEAR:
660 dst->info.clear = src->info.clear;
661 break;
662 case CALL_CLEAR_BUFFER:
663 pipe_resource_reference(&dst->info.clear_buffer.res,
664 src->info.clear_buffer.res);
665 dst->info.clear_buffer = src->info.clear_buffer;
666 break;
667 case CALL_CLEAR_RENDER_TARGET:
668 break;
669 case CALL_CLEAR_DEPTH_STENCIL:
670 break;
671 case CALL_GENERATE_MIPMAP:
672 pipe_resource_reference(&dst->info.generate_mipmap.res,
673 src->info.generate_mipmap.res);
674 dst->info.generate_mipmap = src->info.generate_mipmap;
675 break;
676 }
677 }
678
679 static void
680 dd_init_copy_of_draw_state(struct dd_draw_state_copy *state)
681 {
682 unsigned i,j;
683
684 /* Just clear pointers to gallium objects. Don't clear the whole structure,
685 * because it would kill performance with its size of 130 KB.
686 */
687 memset(&state->base.index_buffer, 0,
688 sizeof(state->base.index_buffer));
689 memset(state->base.vertex_buffers, 0,
690 sizeof(state->base.vertex_buffers));
691 memset(state->base.so_targets, 0,
692 sizeof(state->base.so_targets));
693 memset(state->base.constant_buffers, 0,
694 sizeof(state->base.constant_buffers));
695 memset(state->base.sampler_views, 0,
696 sizeof(state->base.sampler_views));
697 memset(state->base.shader_images, 0,
698 sizeof(state->base.shader_images));
699 memset(state->base.shader_buffers, 0,
700 sizeof(state->base.shader_buffers));
701 memset(&state->base.framebuffer_state, 0,
702 sizeof(state->base.framebuffer_state));
703
704 memset(state->shaders, 0, sizeof(state->shaders));
705
706 state->base.render_cond.query = &state->render_cond;
707
708 for (i = 0; i < PIPE_SHADER_TYPES; i++) {
709 state->base.shaders[i] = &state->shaders[i];
710 for (j = 0; j < PIPE_MAX_SAMPLERS; j++)
711 state->base.sampler_states[i][j] = &state->sampler_states[i][j];
712 }
713
714 state->base.velems = &state->velems;
715 state->base.rs = &state->rs;
716 state->base.dsa = &state->dsa;
717 state->base.blend = &state->blend;
718 }
719
720 static void
721 dd_unreference_copy_of_draw_state(struct dd_draw_state_copy *state)
722 {
723 struct dd_draw_state *dst = &state->base;
724 unsigned i,j;
725
726 util_set_index_buffer(&dst->index_buffer, NULL);
727
728 for (i = 0; i < ARRAY_SIZE(dst->vertex_buffers); i++)
729 pipe_resource_reference(&dst->vertex_buffers[i].buffer, NULL);
730 for (i = 0; i < ARRAY_SIZE(dst->so_targets); i++)
731 pipe_so_target_reference(&dst->so_targets[i], NULL);
732
733 for (i = 0; i < PIPE_SHADER_TYPES; i++) {
734 if (dst->shaders[i])
735 tgsi_free_tokens(dst->shaders[i]->state.shader.tokens);
736
737 for (j = 0; j < PIPE_MAX_CONSTANT_BUFFERS; j++)
738 pipe_resource_reference(&dst->constant_buffers[i][j].buffer, NULL);
739 for (j = 0; j < PIPE_MAX_SAMPLERS; j++)
740 pipe_sampler_view_reference(&dst->sampler_views[i][j], NULL);
741 for (j = 0; j < PIPE_MAX_SHADER_IMAGES; j++)
742 pipe_resource_reference(&dst->shader_images[i][j].resource, NULL);
743 for (j = 0; j < PIPE_MAX_SHADER_BUFFERS; j++)
744 pipe_resource_reference(&dst->shader_buffers[i][j].buffer, NULL);
745 }
746
747 util_unreference_framebuffer_state(&dst->framebuffer_state);
748 }
749
750 static void
751 dd_copy_draw_state(struct dd_draw_state *dst, struct dd_draw_state *src)
752 {
753 unsigned i,j;
754
755 if (src->render_cond.query) {
756 *dst->render_cond.query = *src->render_cond.query;
757 dst->render_cond.condition = src->render_cond.condition;
758 dst->render_cond.mode = src->render_cond.mode;
759 } else {
760 dst->render_cond.query = NULL;
761 }
762
763 util_set_index_buffer(&dst->index_buffer, &src->index_buffer);
764
765 for (i = 0; i < ARRAY_SIZE(src->vertex_buffers); i++) {
766 pipe_resource_reference(&dst->vertex_buffers[i].buffer,
767 src->vertex_buffers[i].buffer);
768 memcpy(&dst->vertex_buffers[i], &src->vertex_buffers[i],
769 sizeof(src->vertex_buffers[i]));
770 }
771
772 dst->num_so_targets = src->num_so_targets;
773 for (i = 0; i < ARRAY_SIZE(src->so_targets); i++)
774 pipe_so_target_reference(&dst->so_targets[i], src->so_targets[i]);
775 memcpy(dst->so_offsets, src->so_offsets, sizeof(src->so_offsets));
776
777 for (i = 0; i < PIPE_SHADER_TYPES; i++) {
778 if (!src->shaders[i]) {
779 dst->shaders[i] = NULL;
780 continue;
781 }
782
783 if (src->shaders[i]) {
784 dst->shaders[i]->state.shader = src->shaders[i]->state.shader;
785 dst->shaders[i]->state.shader.tokens =
786 tgsi_dup_tokens(src->shaders[i]->state.shader.tokens);
787 } else {
788 dst->shaders[i] = NULL;
789 }
790
791 for (j = 0; j < PIPE_MAX_CONSTANT_BUFFERS; j++) {
792 pipe_resource_reference(&dst->constant_buffers[i][j].buffer,
793 src->constant_buffers[i][j].buffer);
794 memcpy(&dst->constant_buffers[i][j], &src->constant_buffers[i][j],
795 sizeof(src->constant_buffers[i][j]));
796 }
797
798 for (j = 0; j < PIPE_MAX_SAMPLERS; j++) {
799 pipe_sampler_view_reference(&dst->sampler_views[i][j],
800 src->sampler_views[i][j]);
801 if (src->sampler_states[i][j])
802 dst->sampler_states[i][j]->state.sampler =
803 src->sampler_states[i][j]->state.sampler;
804 else
805 dst->sampler_states[i][j] = NULL;
806 }
807 /* TODO: shader buffers & images */
808 }
809
810 if (src->velems)
811 dst->velems->state.velems = src->velems->state.velems;
812 else
813 dst->velems = NULL;
814
815 if (src->rs)
816 dst->rs->state.rs = src->rs->state.rs;
817 else
818 dst->rs = NULL;
819
820 if (src->dsa)
821 dst->dsa->state.dsa = src->dsa->state.dsa;
822 else
823 dst->dsa = NULL;
824
825 if (src->blend)
826 dst->blend->state.blend = src->blend->state.blend;
827 else
828 dst->blend = NULL;
829
830 dst->blend_color = src->blend_color;
831 dst->stencil_ref = src->stencil_ref;
832 dst->sample_mask = src->sample_mask;
833 dst->min_samples = src->min_samples;
834 dst->clip_state = src->clip_state;
835 util_copy_framebuffer_state(&dst->framebuffer_state, &src->framebuffer_state);
836 memcpy(dst->scissors, src->scissors, sizeof(src->scissors));
837 memcpy(dst->viewports, src->viewports, sizeof(src->viewports));
838 memcpy(dst->tess_default_levels, src->tess_default_levels,
839 sizeof(src->tess_default_levels));
840 dst->apitrace_call_number = src->apitrace_call_number;
841 }
842
843 static void
844 dd_free_record(struct dd_draw_record **record)
845 {
846 struct dd_draw_record *next = (*record)->next;
847
848 dd_unreference_copy_of_call(&(*record)->call);
849 dd_unreference_copy_of_draw_state(&(*record)->draw_state);
850 FREE((*record)->driver_state_log);
851 FREE(*record);
852 *record = next;
853 }
854
855 static void
856 dd_dump_record(struct dd_context *dctx, struct dd_draw_record *record,
857 uint32_t hw_sequence_no, int64_t now)
858 {
859 FILE *f = dd_get_file_stream(dd_screen(dctx->base.screen),
860 record->draw_state.base.apitrace_call_number);
861 if (!f)
862 return;
863
864 fprintf(f, "Draw call sequence # = %u\n", record->sequence_no);
865 fprintf(f, "HW reached sequence # = %u\n", hw_sequence_no);
866 fprintf(f, "Elapsed time = %"PRIi64" ms\n\n",
867 (now - record->timestamp) / 1000);
868
869 dd_dump_call(f, &record->draw_state.base, &record->call);
870 fprintf(f, "%s\n", record->driver_state_log);
871
872 dctx->pipe->dump_debug_state(dctx->pipe, f,
873 PIPE_DUMP_DEVICE_STATUS_REGISTERS);
874 dd_dump_dmesg(f);
875 fclose(f);
876 }
877
878 PIPE_THREAD_ROUTINE(dd_thread_pipelined_hang_detect, input)
879 {
880 struct dd_context *dctx = (struct dd_context *)input;
881 struct dd_screen *dscreen = dd_screen(dctx->base.screen);
882
883 pipe_mutex_lock(dctx->mutex);
884
885 while (!dctx->kill_thread) {
886 struct dd_draw_record **record = &dctx->records;
887
888 /* Loop over all records. */
889 while (*record) {
890 int64_t now;
891
892 /* If the fence has been signalled, release the record and all older
893 * records.
894 */
895 if (*dctx->mapped_fence >= (*record)->sequence_no) {
896 while (*record)
897 dd_free_record(record);
898 break;
899 }
900
901 /* The fence hasn't been signalled. Check the timeout. */
902 now = os_time_get();
903 if (os_time_timeout((*record)->timestamp,
904 (*record)->timestamp + dscreen->timeout_ms * 1000,
905 now)) {
906 fprintf(stderr, "GPU hang detected.\n");
907
908 /* Get the oldest unsignalled draw call. */
909 while ((*record)->next &&
910 *dctx->mapped_fence < (*record)->next->sequence_no)
911 record = &(*record)->next;
912
913 dd_dump_record(dctx, *record, *dctx->mapped_fence, now);
914 dd_kill_process();
915 }
916
917 record = &(*record)->next;
918 }
919
920 /* Unlock and sleep before starting all over again. */
921 pipe_mutex_unlock(dctx->mutex);
922 os_time_sleep(10000); /* 10 ms */
923 pipe_mutex_lock(dctx->mutex);
924 }
925
926 /* Thread termination. */
927 while (dctx->records)
928 dd_free_record(&dctx->records);
929
930 pipe_mutex_unlock(dctx->mutex);
931 return 0;
932 }
933
934 static char *
935 dd_get_driver_shader_log(struct dd_context *dctx)
936 {
937 #if defined(PIPE_OS_LINUX)
938 FILE *f;
939 char *buf;
940 int written_bytes;
941
942 if (!dctx->max_log_buffer_size)
943 dctx->max_log_buffer_size = 16 * 1024;
944
945 /* Keep increasing the buffer size until there is enough space.
946 *
947 * open_memstream can resize automatically, but it's VERY SLOW.
948 * fmemopen is much faster.
949 */
950 while (1) {
951 buf = malloc(dctx->max_log_buffer_size);
952 buf[0] = 0;
953
954 f = fmemopen(buf, dctx->max_log_buffer_size, "a");
955 if (!f) {
956 free(buf);
957 return NULL;
958 }
959
960 dd_dump_driver_state(dctx, f, PIPE_DUMP_CURRENT_SHADERS);
961 written_bytes = ftell(f);
962 fclose(f);
963
964 /* Return if the backing buffer is large enough. */
965 if (written_bytes < dctx->max_log_buffer_size - 1)
966 break;
967
968 /* Try again. */
969 free(buf);
970 dctx->max_log_buffer_size *= 2;
971 }
972
973 return buf;
974 #else
975 /* Return an empty string. */
976 return (char*)calloc(1, 4);
977 #endif
978 }
979
980 static void
981 dd_pipelined_process_draw(struct dd_context *dctx, struct dd_call *call)
982 {
983 struct pipe_context *pipe = dctx->pipe;
984 struct dd_draw_record *record;
985 char *log;
986
987 /* Make a record of the draw call. */
988 record = MALLOC_STRUCT(dd_draw_record);
989 if (!record)
990 return;
991
992 /* Create the log. */
993 log = dd_get_driver_shader_log(dctx);
994 if (!log) {
995 FREE(record);
996 return;
997 }
998
999 /* Update the fence with the GPU.
1000 *
1001 * radeonsi/clear_buffer waits in the command processor until shaders are
1002 * idle before writing to memory. That's a necessary condition for isolating
1003 * draw calls.
1004 */
1005 dctx->sequence_no++;
1006 pipe->clear_buffer(pipe, dctx->fence, 0, 4, &dctx->sequence_no, 4);
1007
1008 /* Initialize the record. */
1009 record->timestamp = os_time_get();
1010 record->sequence_no = dctx->sequence_no;
1011 record->driver_state_log = log;
1012
1013 memset(&record->call, 0, sizeof(record->call));
1014 dd_copy_call(&record->call, call);
1015
1016 dd_init_copy_of_draw_state(&record->draw_state);
1017 dd_copy_draw_state(&record->draw_state.base, &dctx->draw_state);
1018
1019 /* Add the record to the list. */
1020 pipe_mutex_lock(dctx->mutex);
1021 record->next = dctx->records;
1022 dctx->records = record;
1023 pipe_mutex_unlock(dctx->mutex);
1024 }
1025
1026 static void
1027 dd_context_flush(struct pipe_context *_pipe,
1028 struct pipe_fence_handle **fence, unsigned flags)
1029 {
1030 struct dd_context *dctx = dd_context(_pipe);
1031 struct pipe_context *pipe = dctx->pipe;
1032
1033 switch (dd_screen(dctx->base.screen)->mode) {
1034 case DD_DETECT_HANGS:
1035 dd_flush_and_handle_hang(dctx, fence, flags,
1036 "GPU hang detected in pipe->flush()");
1037 break;
1038 case DD_DETECT_HANGS_PIPELINED: /* nothing to do here */
1039 case DD_DUMP_ALL_CALLS:
1040 case DD_DUMP_APITRACE_CALL:
1041 pipe->flush(pipe, fence, flags);
1042 break;
1043 default:
1044 assert(0);
1045 }
1046 }
1047
1048 static void
1049 dd_before_draw(struct dd_context *dctx)
1050 {
1051 struct dd_screen *dscreen = dd_screen(dctx->base.screen);
1052
1053 if (dscreen->mode == DD_DETECT_HANGS &&
1054 !dscreen->no_flush &&
1055 dctx->num_draw_calls >= dscreen->skip_count)
1056 dd_flush_and_handle_hang(dctx, NULL, 0,
1057 "GPU hang most likely caused by internal "
1058 "driver commands");
1059 }
1060
1061 static void
1062 dd_after_draw(struct dd_context *dctx, struct dd_call *call)
1063 {
1064 struct dd_screen *dscreen = dd_screen(dctx->base.screen);
1065 struct pipe_context *pipe = dctx->pipe;
1066
1067 if (dctx->num_draw_calls >= dscreen->skip_count) {
1068 switch (dscreen->mode) {
1069 case DD_DETECT_HANGS:
1070 if (!dscreen->no_flush &&
1071 dd_flush_and_check_hang(dctx, NULL, 0)) {
1072 dd_write_report(dctx, call,
1073 PIPE_DUMP_DEVICE_STATUS_REGISTERS |
1074 PIPE_DUMP_CURRENT_STATES |
1075 PIPE_DUMP_CURRENT_SHADERS |
1076 PIPE_DUMP_LAST_COMMAND_BUFFER,
1077 true);
1078
1079 /* Terminate the process to prevent future hangs. */
1080 dd_kill_process();
1081 }
1082 break;
1083 case DD_DETECT_HANGS_PIPELINED:
1084 dd_pipelined_process_draw(dctx, call);
1085 break;
1086 case DD_DUMP_ALL_CALLS:
1087 if (!dscreen->no_flush)
1088 pipe->flush(pipe, NULL, 0);
1089 dd_write_report(dctx, call, 0, false);
1090 break;
1091 case DD_DUMP_APITRACE_CALL:
1092 if (dscreen->apitrace_dump_call ==
1093 dctx->draw_state.apitrace_call_number) {
1094 dd_write_report(dctx, call,
1095 PIPE_DUMP_CURRENT_STATES |
1096 PIPE_DUMP_CURRENT_SHADERS,
1097 false);
1098 /* No need to continue. */
1099 exit(0);
1100 }
1101 break;
1102 default:
1103 assert(0);
1104 }
1105 }
1106
1107 ++dctx->num_draw_calls;
1108 if (dscreen->skip_count && dctx->num_draw_calls % 10000 == 0)
1109 fprintf(stderr, "Gallium debugger reached %u draw calls.\n",
1110 dctx->num_draw_calls);
1111 }
1112
1113 static void
1114 dd_context_draw_vbo(struct pipe_context *_pipe,
1115 const struct pipe_draw_info *info)
1116 {
1117 struct dd_context *dctx = dd_context(_pipe);
1118 struct pipe_context *pipe = dctx->pipe;
1119 struct dd_call call;
1120
1121 call.type = CALL_DRAW_VBO;
1122 call.info.draw_vbo = *info;
1123
1124 dd_before_draw(dctx);
1125 pipe->draw_vbo(pipe, info);
1126 dd_after_draw(dctx, &call);
1127 }
1128
1129 static void
1130 dd_context_launch_grid(struct pipe_context *_pipe,
1131 const struct pipe_grid_info *info)
1132 {
1133 struct dd_context *dctx = dd_context(_pipe);
1134 struct pipe_context *pipe = dctx->pipe;
1135 struct dd_call call;
1136
1137 call.type = CALL_LAUNCH_GRID;
1138 call.info.launch_grid = *info;
1139
1140 dd_before_draw(dctx);
1141 pipe->launch_grid(pipe, info);
1142 dd_after_draw(dctx, &call);
1143 }
1144
1145 static void
1146 dd_context_resource_copy_region(struct pipe_context *_pipe,
1147 struct pipe_resource *dst, unsigned dst_level,
1148 unsigned dstx, unsigned dsty, unsigned dstz,
1149 struct pipe_resource *src, unsigned src_level,
1150 const struct pipe_box *src_box)
1151 {
1152 struct dd_context *dctx = dd_context(_pipe);
1153 struct pipe_context *pipe = dctx->pipe;
1154 struct dd_call call;
1155
1156 call.type = CALL_RESOURCE_COPY_REGION;
1157 call.info.resource_copy_region.dst = dst;
1158 call.info.resource_copy_region.dst_level = dst_level;
1159 call.info.resource_copy_region.dstx = dstx;
1160 call.info.resource_copy_region.dsty = dsty;
1161 call.info.resource_copy_region.dstz = dstz;
1162 call.info.resource_copy_region.src = src;
1163 call.info.resource_copy_region.src_level = src_level;
1164 call.info.resource_copy_region.src_box = *src_box;
1165
1166 dd_before_draw(dctx);
1167 pipe->resource_copy_region(pipe,
1168 dst, dst_level, dstx, dsty, dstz,
1169 src, src_level, src_box);
1170 dd_after_draw(dctx, &call);
1171 }
1172
1173 static void
1174 dd_context_blit(struct pipe_context *_pipe, const struct pipe_blit_info *info)
1175 {
1176 struct dd_context *dctx = dd_context(_pipe);
1177 struct pipe_context *pipe = dctx->pipe;
1178 struct dd_call call;
1179
1180 call.type = CALL_BLIT;
1181 call.info.blit = *info;
1182
1183 dd_before_draw(dctx);
1184 pipe->blit(pipe, info);
1185 dd_after_draw(dctx, &call);
1186 }
1187
1188 static boolean
1189 dd_context_generate_mipmap(struct pipe_context *_pipe,
1190 struct pipe_resource *res,
1191 enum pipe_format format,
1192 unsigned base_level,
1193 unsigned last_level,
1194 unsigned first_layer,
1195 unsigned last_layer)
1196 {
1197 struct dd_context *dctx = dd_context(_pipe);
1198 struct pipe_context *pipe = dctx->pipe;
1199 struct dd_call call;
1200 boolean result;
1201
1202 call.type = CALL_GENERATE_MIPMAP;
1203 call.info.generate_mipmap.res = res;
1204 call.info.generate_mipmap.format = format;
1205 call.info.generate_mipmap.base_level = base_level;
1206 call.info.generate_mipmap.last_level = last_level;
1207 call.info.generate_mipmap.first_layer = first_layer;
1208 call.info.generate_mipmap.last_layer = last_layer;
1209
1210 dd_before_draw(dctx);
1211 result = pipe->generate_mipmap(pipe, res, format, base_level, last_level,
1212 first_layer, last_layer);
1213 dd_after_draw(dctx, &call);
1214 return result;
1215 }
1216
1217 static void
1218 dd_context_flush_resource(struct pipe_context *_pipe,
1219 struct pipe_resource *resource)
1220 {
1221 struct dd_context *dctx = dd_context(_pipe);
1222 struct pipe_context *pipe = dctx->pipe;
1223 struct dd_call call;
1224
1225 call.type = CALL_FLUSH_RESOURCE;
1226 call.info.flush_resource = resource;
1227
1228 dd_before_draw(dctx);
1229 pipe->flush_resource(pipe, resource);
1230 dd_after_draw(dctx, &call);
1231 }
1232
1233 static void
1234 dd_context_clear(struct pipe_context *_pipe, unsigned buffers,
1235 const union pipe_color_union *color, double depth,
1236 unsigned stencil)
1237 {
1238 struct dd_context *dctx = dd_context(_pipe);
1239 struct pipe_context *pipe = dctx->pipe;
1240 struct dd_call call;
1241
1242 call.type = CALL_CLEAR;
1243 call.info.clear.buffers = buffers;
1244 call.info.clear.color = *color;
1245 call.info.clear.depth = depth;
1246 call.info.clear.stencil = stencil;
1247
1248 dd_before_draw(dctx);
1249 pipe->clear(pipe, buffers, color, depth, stencil);
1250 dd_after_draw(dctx, &call);
1251 }
1252
1253 static void
1254 dd_context_clear_render_target(struct pipe_context *_pipe,
1255 struct pipe_surface *dst,
1256 const union pipe_color_union *color,
1257 unsigned dstx, unsigned dsty,
1258 unsigned width, unsigned height,
1259 bool render_condition_enabled)
1260 {
1261 struct dd_context *dctx = dd_context(_pipe);
1262 struct pipe_context *pipe = dctx->pipe;
1263 struct dd_call call;
1264
1265 call.type = CALL_CLEAR_RENDER_TARGET;
1266
1267 dd_before_draw(dctx);
1268 pipe->clear_render_target(pipe, dst, color, dstx, dsty, width, height,
1269 render_condition_enabled);
1270 dd_after_draw(dctx, &call);
1271 }
1272
1273 static void
1274 dd_context_clear_depth_stencil(struct pipe_context *_pipe,
1275 struct pipe_surface *dst, unsigned clear_flags,
1276 double depth, unsigned stencil, unsigned dstx,
1277 unsigned dsty, unsigned width, unsigned height,
1278 bool render_condition_enabled)
1279 {
1280 struct dd_context *dctx = dd_context(_pipe);
1281 struct pipe_context *pipe = dctx->pipe;
1282 struct dd_call call;
1283
1284 call.type = CALL_CLEAR_DEPTH_STENCIL;
1285
1286 dd_before_draw(dctx);
1287 pipe->clear_depth_stencil(pipe, dst, clear_flags, depth, stencil,
1288 dstx, dsty, width, height,
1289 render_condition_enabled);
1290 dd_after_draw(dctx, &call);
1291 }
1292
1293 static void
1294 dd_context_clear_buffer(struct pipe_context *_pipe, struct pipe_resource *res,
1295 unsigned offset, unsigned size,
1296 const void *clear_value, int clear_value_size)
1297 {
1298 struct dd_context *dctx = dd_context(_pipe);
1299 struct pipe_context *pipe = dctx->pipe;
1300 struct dd_call call;
1301
1302 call.type = CALL_CLEAR_BUFFER;
1303 call.info.clear_buffer.res = res;
1304 call.info.clear_buffer.offset = offset;
1305 call.info.clear_buffer.size = size;
1306 call.info.clear_buffer.clear_value = clear_value;
1307 call.info.clear_buffer.clear_value_size = clear_value_size;
1308
1309 dd_before_draw(dctx);
1310 pipe->clear_buffer(pipe, res, offset, size, clear_value, clear_value_size);
1311 dd_after_draw(dctx, &call);
1312 }
1313
1314 void
1315 dd_init_draw_functions(struct dd_context *dctx)
1316 {
1317 CTX_INIT(flush);
1318 CTX_INIT(draw_vbo);
1319 CTX_INIT(launch_grid);
1320 CTX_INIT(resource_copy_region);
1321 CTX_INIT(blit);
1322 CTX_INIT(clear);
1323 CTX_INIT(clear_render_target);
1324 CTX_INIT(clear_depth_stencil);
1325 CTX_INIT(clear_buffer);
1326 CTX_INIT(flush_resource);
1327 CTX_INIT(generate_mipmap);
1328 }