Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/auxiliary/driver_ddebug/dd_screen.c
4561 views
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 <ctype.h>
32
#include <stdio.h>
33
34
35
static const char *
36
dd_screen_get_name(struct pipe_screen *_screen)
37
{
38
struct pipe_screen *screen = dd_screen(_screen)->screen;
39
40
return screen->get_name(screen);
41
}
42
43
static const char *
44
dd_screen_get_vendor(struct pipe_screen *_screen)
45
{
46
struct pipe_screen *screen = dd_screen(_screen)->screen;
47
48
return screen->get_vendor(screen);
49
}
50
51
static const char *
52
dd_screen_get_device_vendor(struct pipe_screen *_screen)
53
{
54
struct pipe_screen *screen = dd_screen(_screen)->screen;
55
56
return screen->get_device_vendor(screen);
57
}
58
59
static const void *
60
dd_screen_get_compiler_options(struct pipe_screen *_screen,
61
enum pipe_shader_ir ir,
62
enum pipe_shader_type shader)
63
{
64
struct pipe_screen *screen = dd_screen(_screen)->screen;
65
66
return screen->get_compiler_options(screen, ir, shader);
67
}
68
69
static struct disk_cache *
70
dd_screen_get_disk_shader_cache(struct pipe_screen *_screen)
71
{
72
struct pipe_screen *screen = dd_screen(_screen)->screen;
73
74
return screen->get_disk_shader_cache(screen);
75
}
76
77
static int
78
dd_screen_get_param(struct pipe_screen *_screen,
79
enum pipe_cap param)
80
{
81
struct pipe_screen *screen = dd_screen(_screen)->screen;
82
83
return screen->get_param(screen, param);
84
}
85
86
static float
87
dd_screen_get_paramf(struct pipe_screen *_screen,
88
enum pipe_capf param)
89
{
90
struct pipe_screen *screen = dd_screen(_screen)->screen;
91
92
return screen->get_paramf(screen, param);
93
}
94
95
static int
96
dd_screen_get_compute_param(struct pipe_screen *_screen,
97
enum pipe_shader_ir ir_type,
98
enum pipe_compute_cap param,
99
void *ret)
100
{
101
struct pipe_screen *screen = dd_screen(_screen)->screen;
102
103
return screen->get_compute_param(screen, ir_type, param, ret);
104
}
105
106
static int
107
dd_screen_get_shader_param(struct pipe_screen *_screen,
108
enum pipe_shader_type shader,
109
enum pipe_shader_cap param)
110
{
111
struct pipe_screen *screen = dd_screen(_screen)->screen;
112
113
return screen->get_shader_param(screen, shader, param);
114
}
115
116
static uint64_t
117
dd_screen_get_timestamp(struct pipe_screen *_screen)
118
{
119
struct pipe_screen *screen = dd_screen(_screen)->screen;
120
121
return screen->get_timestamp(screen);
122
}
123
124
static void dd_screen_query_memory_info(struct pipe_screen *_screen,
125
struct pipe_memory_info *info)
126
{
127
struct pipe_screen *screen = dd_screen(_screen)->screen;
128
129
screen->query_memory_info(screen, info);
130
}
131
132
static struct pipe_context *
133
dd_screen_context_create(struct pipe_screen *_screen, void *priv,
134
unsigned flags)
135
{
136
struct dd_screen *dscreen = dd_screen(_screen);
137
struct pipe_screen *screen = dscreen->screen;
138
139
flags |= PIPE_CONTEXT_DEBUG;
140
141
return dd_context_create(dscreen,
142
screen->context_create(screen, priv, flags));
143
}
144
145
static bool
146
dd_screen_is_format_supported(struct pipe_screen *_screen,
147
enum pipe_format format,
148
enum pipe_texture_target target,
149
unsigned sample_count,
150
unsigned storage_sample_count,
151
unsigned tex_usage)
152
{
153
struct pipe_screen *screen = dd_screen(_screen)->screen;
154
155
return screen->is_format_supported(screen, format, target, sample_count,
156
storage_sample_count, tex_usage);
157
}
158
159
static bool
160
dd_screen_can_create_resource(struct pipe_screen *_screen,
161
const struct pipe_resource *templat)
162
{
163
struct pipe_screen *screen = dd_screen(_screen)->screen;
164
165
return screen->can_create_resource(screen, templat);
166
}
167
168
static void
169
dd_screen_flush_frontbuffer(struct pipe_screen *_screen,
170
struct pipe_context *_pipe,
171
struct pipe_resource *resource,
172
unsigned level, unsigned layer,
173
void *context_private,
174
struct pipe_box *sub_box)
175
{
176
struct pipe_screen *screen = dd_screen(_screen)->screen;
177
struct pipe_context *pipe = _pipe ? dd_context(_pipe)->pipe : NULL;
178
179
screen->flush_frontbuffer(screen, pipe, resource, level, layer, context_private,
180
sub_box);
181
}
182
183
static int
184
dd_screen_get_driver_query_info(struct pipe_screen *_screen,
185
unsigned index,
186
struct pipe_driver_query_info *info)
187
{
188
struct pipe_screen *screen = dd_screen(_screen)->screen;
189
190
return screen->get_driver_query_info(screen, index, info);
191
}
192
193
static int
194
dd_screen_get_driver_query_group_info(struct pipe_screen *_screen,
195
unsigned index,
196
struct pipe_driver_query_group_info *info)
197
{
198
struct pipe_screen *screen = dd_screen(_screen)->screen;
199
200
return screen->get_driver_query_group_info(screen, index, info);
201
}
202
203
204
static void
205
dd_screen_get_driver_uuid(struct pipe_screen *_screen, char *uuid)
206
{
207
struct pipe_screen *screen = dd_screen(_screen)->screen;
208
209
screen->get_driver_uuid(screen, uuid);
210
}
211
212
static void
213
dd_screen_get_device_uuid(struct pipe_screen *_screen, char *uuid)
214
{
215
struct pipe_screen *screen = dd_screen(_screen)->screen;
216
217
screen->get_device_uuid(screen, uuid);
218
}
219
220
/********************************************************************
221
* resource
222
*/
223
224
static struct pipe_resource *
225
dd_screen_resource_create(struct pipe_screen *_screen,
226
const struct pipe_resource *templat)
227
{
228
struct pipe_screen *screen = dd_screen(_screen)->screen;
229
struct pipe_resource *res = screen->resource_create(screen, templat);
230
231
if (!res)
232
return NULL;
233
res->screen = _screen;
234
return res;
235
}
236
237
static struct pipe_resource *
238
dd_screen_resource_from_handle(struct pipe_screen *_screen,
239
const struct pipe_resource *templ,
240
struct winsys_handle *handle,
241
unsigned usage)
242
{
243
struct pipe_screen *screen = dd_screen(_screen)->screen;
244
struct pipe_resource *res =
245
screen->resource_from_handle(screen, templ, handle, usage);
246
247
if (!res)
248
return NULL;
249
res->screen = _screen;
250
return res;
251
}
252
253
static struct pipe_resource *
254
dd_screen_resource_from_user_memory(struct pipe_screen *_screen,
255
const struct pipe_resource *templ,
256
void *user_memory)
257
{
258
struct pipe_screen *screen = dd_screen(_screen)->screen;
259
struct pipe_resource *res =
260
screen->resource_from_user_memory(screen, templ, user_memory);
261
262
if (!res)
263
return NULL;
264
res->screen = _screen;
265
return res;
266
}
267
268
static struct pipe_resource *
269
dd_screen_resource_from_memobj(struct pipe_screen *_screen,
270
const struct pipe_resource *templ,
271
struct pipe_memory_object *memobj,
272
uint64_t offset)
273
{
274
struct pipe_screen *screen = dd_screen(_screen)->screen;
275
struct pipe_resource *res =
276
screen->resource_from_memobj(screen, templ, memobj, offset);
277
278
if (!res)
279
return NULL;
280
res->screen = _screen;
281
return res;
282
}
283
284
static void
285
dd_screen_resource_changed(struct pipe_screen *_screen,
286
struct pipe_resource *res)
287
{
288
struct pipe_screen *screen = dd_screen(_screen)->screen;
289
290
if (screen->resource_changed)
291
screen->resource_changed(screen, res);
292
}
293
294
static void
295
dd_screen_resource_destroy(struct pipe_screen *_screen,
296
struct pipe_resource *res)
297
{
298
struct pipe_screen *screen = dd_screen(_screen)->screen;
299
300
screen->resource_destroy(screen, res);
301
}
302
303
static bool
304
dd_screen_resource_get_handle(struct pipe_screen *_screen,
305
struct pipe_context *_pipe,
306
struct pipe_resource *resource,
307
struct winsys_handle *handle,
308
unsigned usage)
309
{
310
struct pipe_screen *screen = dd_screen(_screen)->screen;
311
struct pipe_context *pipe = _pipe ? dd_context(_pipe)->pipe : NULL;
312
313
return screen->resource_get_handle(screen, pipe, resource, handle, usage);
314
}
315
316
static bool
317
dd_screen_resource_get_param(struct pipe_screen *_screen,
318
struct pipe_context *_pipe,
319
struct pipe_resource *resource,
320
unsigned plane,
321
unsigned layer,
322
unsigned level,
323
enum pipe_resource_param param,
324
unsigned handle_usage,
325
uint64_t *value)
326
{
327
struct pipe_screen *screen = dd_screen(_screen)->screen;
328
struct pipe_context *pipe = _pipe ? dd_context(_pipe)->pipe : NULL;
329
330
return screen->resource_get_param(screen, pipe, resource, plane, layer,
331
level, param, handle_usage, value);
332
}
333
334
static void
335
dd_screen_resource_get_info(struct pipe_screen *_screen,
336
struct pipe_resource *resource,
337
unsigned *stride,
338
unsigned *offset)
339
{
340
struct pipe_screen *screen = dd_screen(_screen)->screen;
341
342
screen->resource_get_info(screen, resource, stride, offset);
343
}
344
345
static bool
346
dd_screen_check_resource_capability(struct pipe_screen *_screen,
347
struct pipe_resource *resource,
348
unsigned bind)
349
{
350
struct pipe_screen *screen = dd_screen(_screen)->screen;
351
352
return screen->check_resource_capability(screen, resource, bind);
353
}
354
355
356
/********************************************************************
357
* fence
358
*/
359
360
static void
361
dd_screen_fence_reference(struct pipe_screen *_screen,
362
struct pipe_fence_handle **pdst,
363
struct pipe_fence_handle *src)
364
{
365
struct pipe_screen *screen = dd_screen(_screen)->screen;
366
367
screen->fence_reference(screen, pdst, src);
368
}
369
370
static bool
371
dd_screen_fence_finish(struct pipe_screen *_screen,
372
struct pipe_context *_ctx,
373
struct pipe_fence_handle *fence,
374
uint64_t timeout)
375
{
376
struct pipe_screen *screen = dd_screen(_screen)->screen;
377
struct pipe_context *ctx = _ctx ? dd_context(_ctx)->pipe : NULL;
378
379
return screen->fence_finish(screen, ctx, fence, timeout);
380
}
381
382
static int
383
dd_screen_fence_get_fd(struct pipe_screen *_screen,
384
struct pipe_fence_handle *fence)
385
{
386
struct pipe_screen *screen = dd_screen(_screen)->screen;
387
388
return screen->fence_get_fd(screen, fence);
389
}
390
391
/********************************************************************
392
* memobj
393
*/
394
395
static struct pipe_memory_object *
396
dd_screen_memobj_create_from_handle(struct pipe_screen *_screen,
397
struct winsys_handle *handle,
398
bool dedicated)
399
{
400
struct pipe_screen *screen = dd_screen(_screen)->screen;
401
402
return screen->memobj_create_from_handle(screen, handle, dedicated);
403
}
404
405
static void
406
dd_screen_memobj_destroy(struct pipe_screen *_screen,
407
struct pipe_memory_object *memobj)
408
{
409
struct pipe_screen *screen = dd_screen(_screen)->screen;
410
411
screen->memobj_destroy(screen, memobj);
412
}
413
/********************************************************************
414
* screen
415
*/
416
417
static void
418
dd_screen_finalize_nir(struct pipe_screen *_screen, void *nir, bool optimize)
419
{
420
struct pipe_screen *screen = dd_screen(_screen)->screen;
421
422
screen->finalize_nir(screen, nir, optimize);
423
}
424
425
static void
426
dd_screen_destroy(struct pipe_screen *_screen)
427
{
428
struct dd_screen *dscreen = dd_screen(_screen);
429
struct pipe_screen *screen = dscreen->screen;
430
431
screen->destroy(screen);
432
FREE(dscreen);
433
}
434
435
static void
436
skip_space(const char **p)
437
{
438
while (isspace(**p))
439
(*p)++;
440
}
441
442
static bool
443
match_word(const char **cur, const char *word)
444
{
445
size_t len = strlen(word);
446
if (strncmp(*cur, word, len) != 0)
447
return false;
448
449
const char *p = *cur + len;
450
if (*p) {
451
if (!isspace(*p))
452
return false;
453
454
*cur = p + 1;
455
} else {
456
*cur = p;
457
}
458
459
return true;
460
}
461
462
static bool
463
match_uint(const char **cur, unsigned *value)
464
{
465
char *end;
466
unsigned v = strtoul(*cur, &end, 0);
467
if (end == *cur || (*end && !isspace(*end)))
468
return false;
469
*cur = end;
470
*value = v;
471
return true;
472
}
473
474
struct pipe_screen *
475
ddebug_screen_create(struct pipe_screen *screen)
476
{
477
struct dd_screen *dscreen;
478
const char *option;
479
bool flush = false;
480
bool verbose = false;
481
bool transfers = false;
482
unsigned timeout = 1000;
483
unsigned apitrace_dump_call = 0;
484
enum dd_dump_mode mode = DD_DUMP_ONLY_HANGS;
485
486
option = debug_get_option("GALLIUM_DDEBUG", NULL);
487
if (!option)
488
return screen;
489
490
if (!strcmp(option, "help")) {
491
puts("Gallium driver debugger");
492
puts("");
493
puts("Usage:");
494
puts("");
495
puts(" GALLIUM_DDEBUG=\"[<timeout in ms>] [(always|apitrace <call#)] [flush] [transfers] [verbose]\"");
496
puts(" GALLIUM_DDEBUG_SKIP=[count]");
497
puts("");
498
puts("Dump context and driver information of draw calls into");
499
puts("$HOME/"DD_DIR"/. By default, watch for GPU hangs and only dump information");
500
puts("about draw calls related to the hang.");
501
puts("");
502
puts("<timeout in ms>");
503
puts(" Change the default timeout for GPU hang detection (default=1000ms).");
504
puts(" Setting this to 0 will disable GPU hang detection entirely.");
505
puts("");
506
puts("always");
507
puts(" Dump information about all draw calls.");
508
puts("");
509
puts("transfers");
510
puts(" Also dump and do hang detection on transfers.");
511
puts("");
512
puts("apitrace <call#>");
513
puts(" Dump information about the draw call corresponding to the given");
514
puts(" apitrace call number and exit.");
515
puts("");
516
puts("flush");
517
puts(" Flush after every draw call.");
518
puts("");
519
puts("verbose");
520
puts(" Write additional information to stderr.");
521
puts("");
522
puts("GALLIUM_DDEBUG_SKIP=count");
523
puts(" Skip dumping on the first count draw calls (only relevant with 'always').");
524
puts("");
525
exit(0);
526
}
527
528
for (;;) {
529
skip_space(&option);
530
if (!*option)
531
break;
532
533
if (match_word(&option, "always")) {
534
if (mode == DD_DUMP_APITRACE_CALL) {
535
printf("ddebug: both 'always' and 'apitrace' specified\n");
536
exit(1);
537
}
538
539
mode = DD_DUMP_ALL_CALLS;
540
} else if (match_word(&option, "flush")) {
541
flush = true;
542
} else if (match_word(&option, "transfers")) {
543
transfers = true;
544
} else if (match_word(&option, "verbose")) {
545
verbose = true;
546
} else if (match_word(&option, "apitrace")) {
547
if (mode != DD_DUMP_ONLY_HANGS) {
548
printf("ddebug: 'apitrace' can only appear once and not mixed with 'always'\n");
549
exit(1);
550
}
551
552
if (!match_uint(&option, &apitrace_dump_call)) {
553
printf("ddebug: expected call number after 'apitrace'\n");
554
exit(1);
555
}
556
557
mode = DD_DUMP_APITRACE_CALL;
558
} else if (match_uint(&option, &timeout)) {
559
/* no-op */
560
} else {
561
printf("ddebug: bad options: %s\n", option);
562
exit(1);
563
}
564
}
565
566
dscreen = CALLOC_STRUCT(dd_screen);
567
if (!dscreen)
568
return NULL;
569
570
#define SCR_INIT(_member) \
571
dscreen->base._member = screen->_member ? dd_screen_##_member : NULL
572
573
dscreen->base.destroy = dd_screen_destroy;
574
dscreen->base.get_name = dd_screen_get_name;
575
dscreen->base.get_vendor = dd_screen_get_vendor;
576
dscreen->base.get_device_vendor = dd_screen_get_device_vendor;
577
SCR_INIT(get_disk_shader_cache);
578
dscreen->base.get_param = dd_screen_get_param;
579
dscreen->base.get_paramf = dd_screen_get_paramf;
580
dscreen->base.get_compute_param = dd_screen_get_compute_param;
581
dscreen->base.get_shader_param = dd_screen_get_shader_param;
582
dscreen->base.query_memory_info = dd_screen_query_memory_info;
583
/* get_video_param */
584
/* get_compute_param */
585
SCR_INIT(get_timestamp);
586
dscreen->base.context_create = dd_screen_context_create;
587
dscreen->base.is_format_supported = dd_screen_is_format_supported;
588
/* is_video_format_supported */
589
SCR_INIT(can_create_resource);
590
dscreen->base.resource_create = dd_screen_resource_create;
591
dscreen->base.resource_from_handle = dd_screen_resource_from_handle;
592
SCR_INIT(resource_from_memobj);
593
SCR_INIT(resource_from_user_memory);
594
SCR_INIT(check_resource_capability);
595
dscreen->base.resource_get_handle = dd_screen_resource_get_handle;
596
SCR_INIT(resource_get_param);
597
SCR_INIT(resource_get_info);
598
SCR_INIT(resource_changed);
599
dscreen->base.resource_destroy = dd_screen_resource_destroy;
600
SCR_INIT(flush_frontbuffer);
601
SCR_INIT(fence_reference);
602
SCR_INIT(fence_finish);
603
SCR_INIT(fence_get_fd);
604
SCR_INIT(memobj_create_from_handle);
605
SCR_INIT(memobj_destroy);
606
SCR_INIT(get_driver_query_info);
607
SCR_INIT(get_driver_query_group_info);
608
SCR_INIT(get_compiler_options);
609
SCR_INIT(get_driver_uuid);
610
SCR_INIT(get_device_uuid);
611
SCR_INIT(finalize_nir);
612
613
#undef SCR_INIT
614
615
dscreen->screen = screen;
616
dscreen->timeout_ms = timeout;
617
dscreen->dump_mode = mode;
618
dscreen->flush_always = flush;
619
dscreen->transfers = transfers;
620
dscreen->verbose = verbose;
621
dscreen->apitrace_dump_call = apitrace_dump_call;
622
623
switch (dscreen->dump_mode) {
624
case DD_DUMP_ALL_CALLS:
625
fprintf(stderr, "Gallium debugger active. Logging all calls.\n");
626
break;
627
case DD_DUMP_APITRACE_CALL:
628
fprintf(stderr, "Gallium debugger active. Going to dump an apitrace call.\n");
629
break;
630
default:
631
fprintf(stderr, "Gallium debugger active.\n");
632
break;
633
}
634
635
if (dscreen->timeout_ms > 0)
636
fprintf(stderr, "Hang detection timeout is %ums.\n", dscreen->timeout_ms);
637
else
638
fprintf(stderr, "Hang detection is disabled.\n");
639
640
dscreen->skip_count = debug_get_num_option("GALLIUM_DDEBUG_SKIP", 0);
641
if (dscreen->skip_count > 0) {
642
fprintf(stderr, "Gallium debugger skipping the first %u draw calls.\n",
643
dscreen->skip_count);
644
}
645
646
return &dscreen->base;
647
}
648
649