ddebug/rbug/trace: add get_disk_shader_cache() to pass-throughs
[mesa.git] / src / gallium / drivers / ddebug / dd_screen.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 #include "dd_public.h"
30 #include "util/u_memory.h"
31 #include <stdio.h>
32
33
34 static const char *
35 dd_screen_get_name(struct pipe_screen *_screen)
36 {
37 struct pipe_screen *screen = dd_screen(_screen)->screen;
38
39 return screen->get_name(screen);
40 }
41
42 static const char *
43 dd_screen_get_vendor(struct pipe_screen *_screen)
44 {
45 struct pipe_screen *screen = dd_screen(_screen)->screen;
46
47 return screen->get_vendor(screen);
48 }
49
50 static const char *
51 dd_screen_get_device_vendor(struct pipe_screen *_screen)
52 {
53 struct pipe_screen *screen = dd_screen(_screen)->screen;
54
55 return screen->get_device_vendor(screen);
56 }
57
58 static struct disk_cache *
59 dd_screen_get_disk_shader_cache(struct pipe_screen *_screen)
60 {
61 struct pipe_screen *screen = dd_screen(_screen)->screen;
62
63 return screen->get_disk_shader_cache(screen);
64 }
65
66 static int
67 dd_screen_get_param(struct pipe_screen *_screen,
68 enum pipe_cap param)
69 {
70 struct pipe_screen *screen = dd_screen(_screen)->screen;
71
72 return screen->get_param(screen, param);
73 }
74
75 static float
76 dd_screen_get_paramf(struct pipe_screen *_screen,
77 enum pipe_capf param)
78 {
79 struct pipe_screen *screen = dd_screen(_screen)->screen;
80
81 return screen->get_paramf(screen, param);
82 }
83
84 static int
85 dd_screen_get_compute_param(struct pipe_screen *_screen,
86 enum pipe_shader_ir ir_type,
87 enum pipe_compute_cap param,
88 void *ret)
89 {
90 struct pipe_screen *screen = dd_screen(_screen)->screen;
91
92 return screen->get_compute_param(screen, ir_type, param, ret);
93 }
94
95 static int
96 dd_screen_get_shader_param(struct pipe_screen *_screen, unsigned shader,
97 enum pipe_shader_cap param)
98 {
99 struct pipe_screen *screen = dd_screen(_screen)->screen;
100
101 return screen->get_shader_param(screen, shader, param);
102 }
103
104 static uint64_t
105 dd_screen_get_timestamp(struct pipe_screen *_screen)
106 {
107 struct pipe_screen *screen = dd_screen(_screen)->screen;
108
109 return screen->get_timestamp(screen);
110 }
111
112 static void dd_screen_query_memory_info(struct pipe_screen *_screen,
113 struct pipe_memory_info *info)
114 {
115 struct pipe_screen *screen = dd_screen(_screen)->screen;
116
117 return screen->query_memory_info(screen, info);
118 }
119
120 static struct pipe_context *
121 dd_screen_context_create(struct pipe_screen *_screen, void *priv,
122 unsigned flags)
123 {
124 struct dd_screen *dscreen = dd_screen(_screen);
125 struct pipe_screen *screen = dscreen->screen;
126
127 flags |= PIPE_CONTEXT_DEBUG;
128
129 return dd_context_create(dscreen,
130 screen->context_create(screen, priv, flags));
131 }
132
133 static boolean
134 dd_screen_is_format_supported(struct pipe_screen *_screen,
135 enum pipe_format format,
136 enum pipe_texture_target target,
137 unsigned sample_count,
138 unsigned tex_usage)
139 {
140 struct pipe_screen *screen = dd_screen(_screen)->screen;
141
142 return screen->is_format_supported(screen, format, target, sample_count,
143 tex_usage);
144 }
145
146 static boolean
147 dd_screen_can_create_resource(struct pipe_screen *_screen,
148 const struct pipe_resource *templat)
149 {
150 struct pipe_screen *screen = dd_screen(_screen)->screen;
151
152 return screen->can_create_resource(screen, templat);
153 }
154
155 static void
156 dd_screen_flush_frontbuffer(struct pipe_screen *_screen,
157 struct pipe_resource *resource,
158 unsigned level, unsigned layer,
159 void *context_private,
160 struct pipe_box *sub_box)
161 {
162 struct pipe_screen *screen = dd_screen(_screen)->screen;
163
164 screen->flush_frontbuffer(screen, resource, level, layer, context_private,
165 sub_box);
166 }
167
168 static int
169 dd_screen_get_driver_query_info(struct pipe_screen *_screen,
170 unsigned index,
171 struct pipe_driver_query_info *info)
172 {
173 struct pipe_screen *screen = dd_screen(_screen)->screen;
174
175 return screen->get_driver_query_info(screen, index, info);
176 }
177
178 static int
179 dd_screen_get_driver_query_group_info(struct pipe_screen *_screen,
180 unsigned index,
181 struct pipe_driver_query_group_info *info)
182 {
183 struct pipe_screen *screen = dd_screen(_screen)->screen;
184
185 return screen->get_driver_query_group_info(screen, index, info);
186 }
187
188
189 /********************************************************************
190 * resource
191 */
192
193 static struct pipe_resource *
194 dd_screen_resource_create(struct pipe_screen *_screen,
195 const struct pipe_resource *templat)
196 {
197 struct pipe_screen *screen = dd_screen(_screen)->screen;
198 struct pipe_resource *res = screen->resource_create(screen, templat);
199
200 if (!res)
201 return NULL;
202 res->screen = _screen;
203 return res;
204 }
205
206 static struct pipe_resource *
207 dd_screen_resource_from_handle(struct pipe_screen *_screen,
208 const struct pipe_resource *templ,
209 struct winsys_handle *handle,
210 unsigned usage)
211 {
212 struct pipe_screen *screen = dd_screen(_screen)->screen;
213 struct pipe_resource *res =
214 screen->resource_from_handle(screen, templ, handle, usage);
215
216 if (!res)
217 return NULL;
218 res->screen = _screen;
219 return res;
220 }
221
222 static struct pipe_resource *
223 dd_screen_resource_from_user_memory(struct pipe_screen *_screen,
224 const struct pipe_resource *templ,
225 void *user_memory)
226 {
227 struct pipe_screen *screen = dd_screen(_screen)->screen;
228 struct pipe_resource *res =
229 screen->resource_from_user_memory(screen, templ, user_memory);
230
231 if (!res)
232 return NULL;
233 res->screen = _screen;
234 return res;
235 }
236
237 static void
238 dd_screen_resource_changed(struct pipe_screen *_screen,
239 struct pipe_resource *res)
240 {
241 struct pipe_screen *screen = dd_screen(_screen)->screen;
242
243 screen->resource_changed(screen, res);
244 }
245
246 static void
247 dd_screen_resource_destroy(struct pipe_screen *_screen,
248 struct pipe_resource *res)
249 {
250 struct pipe_screen *screen = dd_screen(_screen)->screen;
251
252 screen->resource_destroy(screen, res);
253 }
254
255 static boolean
256 dd_screen_resource_get_handle(struct pipe_screen *_screen,
257 struct pipe_context *_pipe,
258 struct pipe_resource *resource,
259 struct winsys_handle *handle,
260 unsigned usage)
261 {
262 struct pipe_screen *screen = dd_screen(_screen)->screen;
263 struct pipe_context *pipe = _pipe ? dd_context(_pipe)->pipe : NULL;
264
265 return screen->resource_get_handle(screen, pipe, resource, handle, usage);
266 }
267
268
269 /********************************************************************
270 * fence
271 */
272
273 static void
274 dd_screen_fence_reference(struct pipe_screen *_screen,
275 struct pipe_fence_handle **pdst,
276 struct pipe_fence_handle *src)
277 {
278 struct pipe_screen *screen = dd_screen(_screen)->screen;
279
280 screen->fence_reference(screen, pdst, src);
281 }
282
283 static boolean
284 dd_screen_fence_finish(struct pipe_screen *_screen,
285 struct pipe_context *_ctx,
286 struct pipe_fence_handle *fence,
287 uint64_t timeout)
288 {
289 struct pipe_screen *screen = dd_screen(_screen)->screen;
290 struct pipe_context *ctx = _ctx ? dd_context(_ctx)->pipe : NULL;
291
292 return screen->fence_finish(screen, ctx, fence, timeout);
293 }
294
295
296 /********************************************************************
297 * screen
298 */
299
300 static void
301 dd_screen_destroy(struct pipe_screen *_screen)
302 {
303 struct dd_screen *dscreen = dd_screen(_screen);
304 struct pipe_screen *screen = dscreen->screen;
305
306 screen->destroy(screen);
307 FREE(dscreen);
308 }
309
310 struct pipe_screen *
311 ddebug_screen_create(struct pipe_screen *screen)
312 {
313 struct dd_screen *dscreen;
314 const char *option;
315 bool no_flush;
316 unsigned timeout = 0;
317 unsigned apitrace_dump_call = 0;
318 enum dd_mode mode;
319
320 option = debug_get_option("GALLIUM_DDEBUG", NULL);
321 if (!option)
322 return screen;
323
324 if (!strcmp(option, "help")) {
325 puts("Gallium driver debugger");
326 puts("");
327 puts("Usage:");
328 puts("");
329 puts(" GALLIUM_DDEBUG=\"always [noflush] [verbose]\"");
330 puts(" Flush and dump context and driver information after every draw call into");
331 puts(" $HOME/"DD_DIR"/.");
332 puts("");
333 puts(" GALLIUM_DDEBUG=\"[timeout in ms] [noflush] [verbose]\"");
334 puts(" Flush and detect a device hang after every draw call based on the given");
335 puts(" fence timeout and dump context and driver information into");
336 puts(" $HOME/"DD_DIR"/ when a hang is detected.");
337 puts("");
338 puts(" GALLIUM_DDEBUG=\"pipelined [timeout in ms] [verbose]\"");
339 puts(" Detect a device hang after every draw call based on the given fence");
340 puts(" timeout without flushes and dump context and driver information into");
341 puts(" $HOME/"DD_DIR"/ when a hang is detected.");
342 puts("");
343 puts(" GALLIUM_DDEBUG=\"apitrace [call#] [verbose]\"");
344 puts(" Dump apitrace draw call information into $HOME/"DD_DIR"/. Implies 'noflush'.");
345 puts("");
346 puts(" If 'noflush' is specified, do not flush on every draw call. In hang");
347 puts(" detection mode, this only detect hangs in pipe->flush.");
348 puts(" If 'verbose' is specified, additional information is written to stderr.");
349 puts("");
350 puts(" GALLIUM_DDEBUG_SKIP=[count]");
351 puts(" Skip flush and hang detection for the given initial number of draw calls.");
352 puts("");
353 exit(0);
354 }
355
356 no_flush = strstr(option, "noflush") != NULL;
357
358 if (!strncmp(option, "always", 6)) {
359 mode = DD_DUMP_ALL_CALLS;
360 } else if (!strncmp(option, "apitrace", 8)) {
361 mode = DD_DUMP_APITRACE_CALL;
362 no_flush = true;
363
364 if (sscanf(option+8, "%u", &apitrace_dump_call) != 1)
365 return screen;
366 } else if (!strncmp(option, "pipelined", 8)) {
367 mode = DD_DETECT_HANGS_PIPELINED;
368
369 if (sscanf(option+10, "%u", &timeout) != 1)
370 return screen;
371 } else {
372 mode = DD_DETECT_HANGS;
373
374 if (sscanf(option, "%u", &timeout) != 1)
375 return screen;
376 }
377
378 dscreen = CALLOC_STRUCT(dd_screen);
379 if (!dscreen)
380 return NULL;
381
382 #define SCR_INIT(_member) \
383 dscreen->base._member = screen->_member ? dd_screen_##_member : NULL
384
385 dscreen->base.destroy = dd_screen_destroy;
386 dscreen->base.get_name = dd_screen_get_name;
387 dscreen->base.get_vendor = dd_screen_get_vendor;
388 dscreen->base.get_device_vendor = dd_screen_get_device_vendor;
389 SCR_INIT(get_disk_shader_cache);
390 dscreen->base.get_param = dd_screen_get_param;
391 dscreen->base.get_paramf = dd_screen_get_paramf;
392 dscreen->base.get_compute_param = dd_screen_get_compute_param;
393 dscreen->base.get_shader_param = dd_screen_get_shader_param;
394 dscreen->base.query_memory_info = dd_screen_query_memory_info;
395 /* get_video_param */
396 /* get_compute_param */
397 SCR_INIT(get_timestamp);
398 dscreen->base.context_create = dd_screen_context_create;
399 dscreen->base.is_format_supported = dd_screen_is_format_supported;
400 /* is_video_format_supported */
401 SCR_INIT(can_create_resource);
402 dscreen->base.resource_create = dd_screen_resource_create;
403 dscreen->base.resource_from_handle = dd_screen_resource_from_handle;
404 SCR_INIT(resource_from_user_memory);
405 dscreen->base.resource_get_handle = dd_screen_resource_get_handle;
406 SCR_INIT(resource_changed);
407 dscreen->base.resource_destroy = dd_screen_resource_destroy;
408 SCR_INIT(flush_frontbuffer);
409 SCR_INIT(fence_reference);
410 SCR_INIT(fence_finish);
411 SCR_INIT(get_driver_query_info);
412 SCR_INIT(get_driver_query_group_info);
413
414 #undef SCR_INIT
415
416 dscreen->screen = screen;
417 dscreen->timeout_ms = timeout;
418 dscreen->mode = mode;
419 dscreen->no_flush = no_flush;
420 dscreen->verbose = strstr(option, "verbose") != NULL;
421 dscreen->apitrace_dump_call = apitrace_dump_call;
422
423 switch (dscreen->mode) {
424 case DD_DUMP_ALL_CALLS:
425 fprintf(stderr, "Gallium debugger active. Logging all calls.\n");
426 break;
427 case DD_DETECT_HANGS:
428 case DD_DETECT_HANGS_PIPELINED:
429 fprintf(stderr, "Gallium debugger active. "
430 "The hang detection timeout is %i ms.\n", timeout);
431 break;
432 case DD_DUMP_APITRACE_CALL:
433 fprintf(stderr, "Gallium debugger active. Going to dump an apitrace call.\n");
434 break;
435 default:
436 assert(0);
437 }
438
439 dscreen->skip_count = debug_get_num_option("GALLIUM_DDEBUG_SKIP", 0);
440 if (dscreen->skip_count > 0) {
441 fprintf(stderr, "Gallium debugger skipping the first %u draw calls.\n",
442 dscreen->skip_count);
443 }
444
445 return &dscreen->base;
446 }