Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/intel/tools/aubinator_viewer_decoder.cpp
4547 views
1
/*
2
* Copyright © 2017 Intel Corporation
3
*
4
* Permission is hereby granted, free of charge, to any person obtaining a
5
* copy of this software and associated documentation files (the "Software"),
6
* to deal in the Software without restriction, including without limitation
7
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
* and/or sell copies of the Software, and to permit persons to whom the
9
* Software is furnished to do so, subject to the following conditions:
10
*
11
* The above copyright notice and this permission notice (including the next
12
* paragraph) shall be included in all copies or substantial portions of the
13
* Software.
14
*
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
* IN THE SOFTWARE.
22
*/
23
24
#include <string.h>
25
26
#include "util/macros.h"
27
28
#include "aubinator_viewer.h"
29
30
void
31
aub_viewer_decode_ctx_init(struct aub_viewer_decode_ctx *ctx,
32
struct aub_viewer_cfg *cfg,
33
struct aub_viewer_decode_cfg *decode_cfg,
34
const struct intel_device_info *devinfo,
35
struct intel_spec *spec,
36
struct intel_batch_decode_bo (*get_bo)(void *, bool, uint64_t),
37
unsigned (*get_state_size)(void *, uint32_t),
38
void *user_data)
39
{
40
memset(ctx, 0, sizeof(*ctx));
41
42
ctx->get_bo = get_bo;
43
ctx->get_state_size = get_state_size;
44
ctx->user_data = user_data;
45
ctx->devinfo = devinfo;
46
ctx->engine = I915_ENGINE_CLASS_RENDER;
47
48
ctx->cfg = cfg;
49
ctx->decode_cfg = decode_cfg;
50
ctx->spec = spec;
51
}
52
53
static void
54
aub_viewer_print_group(struct aub_viewer_decode_ctx *ctx,
55
struct intel_group *group,
56
uint64_t address, const void *map)
57
{
58
struct intel_field_iterator iter;
59
int last_dword = -1;
60
const uint32_t *p = (const uint32_t *) map;
61
62
intel_field_iterator_init(&iter, group, p, 0, false);
63
while (intel_field_iterator_next(&iter)) {
64
if (ctx->decode_cfg->show_dwords) {
65
int iter_dword = iter.end_bit / 32;
66
if (last_dword != iter_dword) {
67
for (int i = last_dword + 1; i <= iter_dword; i++) {
68
ImGui::TextColored(ctx->cfg->dwords_color,
69
"0x%012" PRIx64 ": 0x%012x : Dword %d",
70
address + 4 * i, iter.p[i], i);
71
}
72
last_dword = iter_dword;
73
}
74
}
75
if (!intel_field_is_header(iter.field)) {
76
if (ctx->decode_cfg->field_filter.PassFilter(iter.name)) {
77
if (iter.field->type.kind == intel_type::INTEL_TYPE_BOOL && iter.raw_value) {
78
ImGui::Text("%s: ", iter.name); ImGui::SameLine();
79
ImGui::TextColored(ctx->cfg->boolean_color, "true");
80
} else {
81
ImGui::Text("%s: %s", iter.name, iter.value);
82
}
83
if (iter.struct_desc) {
84
int struct_dword = iter.start_bit / 32;
85
uint64_t struct_address = address + 4 * struct_dword;
86
aub_viewer_print_group(ctx, iter.struct_desc, struct_address,
87
&p[struct_dword]);
88
}
89
}
90
}
91
}
92
}
93
94
static struct intel_batch_decode_bo
95
ctx_get_bo(struct aub_viewer_decode_ctx *ctx, bool ppgtt, uint64_t addr)
96
{
97
if (intel_spec_get_gen(ctx->spec) >= intel_make_gen(8,0)) {
98
/* On Broadwell and above, we have 48-bit addresses which consume two
99
* dwords. Some packets require that these get stored in a "canonical
100
* form" which means that bit 47 is sign-extended through the upper
101
* bits. In order to correctly handle those aub dumps, we need to mask
102
* off the top 16 bits.
103
*/
104
addr &= (~0ull >> 16);
105
}
106
107
struct intel_batch_decode_bo bo = ctx->get_bo(ctx->user_data, ppgtt, addr);
108
109
if (intel_spec_get_gen(ctx->spec) >= intel_make_gen(8,0))
110
bo.addr &= (~0ull >> 16);
111
112
/* We may actually have an offset into the bo */
113
if (bo.map != NULL) {
114
assert(bo.addr <= addr);
115
uint64_t offset = addr - bo.addr;
116
bo.map = (const uint8_t *)bo.map + offset;
117
bo.addr += offset;
118
bo.size -= offset;
119
}
120
121
return bo;
122
}
123
124
static int
125
update_count(struct aub_viewer_decode_ctx *ctx,
126
uint32_t offset_from_dsba,
127
unsigned element_dwords,
128
unsigned guess)
129
{
130
unsigned size = 0;
131
132
if (ctx->get_state_size)
133
size = ctx->get_state_size(ctx->user_data, offset_from_dsba);
134
135
if (size > 0)
136
return size / (sizeof(uint32_t) * element_dwords);
137
138
/* In the absence of any information, just guess arbitrarily. */
139
return guess;
140
}
141
142
static void
143
ctx_disassemble_program(struct aub_viewer_decode_ctx *ctx,
144
uint32_t ksp, const char *type)
145
{
146
uint64_t addr = ctx->instruction_base + ksp;
147
struct intel_batch_decode_bo bo = ctx_get_bo(ctx, true, addr);
148
if (!bo.map) {
149
ImGui::TextColored(ctx->cfg->missing_color,
150
"Shader unavailable addr=0x%012" PRIx64, addr);
151
return;
152
}
153
154
ImGui::PushID(addr);
155
if (ImGui::Button(type) && ctx->display_shader)
156
ctx->display_shader(ctx->user_data, type, addr);
157
ImGui::PopID();
158
}
159
160
static void
161
handle_state_base_address(struct aub_viewer_decode_ctx *ctx,
162
struct intel_group *inst,
163
const uint32_t *p)
164
{
165
struct intel_field_iterator iter;
166
intel_field_iterator_init(&iter, inst, p, 0, false);
167
168
uint64_t surface_base = 0, dynamic_base = 0, instruction_base = 0;
169
bool surface_modify = 0, dynamic_modify = 0, instruction_modify = 0;
170
171
while (intel_field_iterator_next(&iter)) {
172
if (strcmp(iter.name, "Surface State Base Address") == 0) {
173
surface_base = iter.raw_value;
174
} else if (strcmp(iter.name, "Dynamic State Base Address") == 0) {
175
dynamic_base = iter.raw_value;
176
} else if (strcmp(iter.name, "Instruction Base Address") == 0) {
177
instruction_base = iter.raw_value;
178
} else if (strcmp(iter.name, "Surface State Base Address Modify Enable") == 0) {
179
surface_modify = iter.raw_value;
180
} else if (strcmp(iter.name, "Dynamic State Base Address Modify Enable") == 0) {
181
dynamic_modify = iter.raw_value;
182
} else if (strcmp(iter.name, "Instruction Base Address Modify Enable") == 0) {
183
instruction_modify = iter.raw_value;
184
}
185
}
186
187
if (dynamic_modify)
188
ctx->dynamic_base = dynamic_base;
189
190
if (surface_modify)
191
ctx->surface_base = surface_base;
192
193
if (instruction_modify)
194
ctx->instruction_base = instruction_base;
195
}
196
197
static void
198
dump_binding_table(struct aub_viewer_decode_ctx *ctx, uint32_t offset, int count)
199
{
200
struct intel_group *strct =
201
intel_spec_find_struct(ctx->spec, "RENDER_SURFACE_STATE");
202
if (strct == NULL) {
203
ImGui::TextColored(ctx->cfg->missing_color, "did not find RENDER_SURFACE_STATE info");
204
return;
205
}
206
207
if (count < 0)
208
count = update_count(ctx, offset, 1, 8);
209
210
if (offset % 32 != 0 || offset >= UINT16_MAX) {
211
ImGui::TextColored(ctx->cfg->missing_color, "invalid binding table pointer");
212
return;
213
}
214
215
struct intel_batch_decode_bo bind_bo =
216
ctx_get_bo(ctx, true, ctx->surface_base + offset);
217
218
if (bind_bo.map == NULL) {
219
ImGui::TextColored(ctx->cfg->missing_color,
220
"binding table unavailable addr=0x%012" PRIx64,
221
ctx->surface_base + offset);
222
return;
223
}
224
225
const uint32_t *pointers = (const uint32_t *) bind_bo.map;
226
for (int i = 0; i < count; i++) {
227
if (pointers[i] == 0)
228
continue;
229
230
uint64_t addr = ctx->surface_base + pointers[i];
231
struct intel_batch_decode_bo bo = ctx_get_bo(ctx, true, addr);
232
uint32_t size = strct->dw_length * 4;
233
234
if (pointers[i] % 32 != 0 ||
235
addr < bo.addr || addr + size >= bo.addr + bo.size) {
236
ImGui::TextColored(ctx->cfg->missing_color,
237
"pointer %u: %012x <not valid>", i, pointers[i]);
238
continue;
239
}
240
241
const uint8_t *state = (const uint8_t *) bo.map + (addr - bo.addr);
242
if (ImGui::TreeNodeEx(&pointers[i], ImGuiTreeNodeFlags_Framed,
243
"pointer %u: %012x", i, pointers[i])) {
244
aub_viewer_print_group(ctx, strct, addr, state);
245
ImGui::TreePop();
246
}
247
}
248
}
249
250
static void
251
dump_samplers(struct aub_viewer_decode_ctx *ctx, uint32_t offset, int count)
252
{
253
struct intel_group *strct = intel_spec_find_struct(ctx->spec, "SAMPLER_STATE");
254
255
uint64_t state_addr = ctx->dynamic_base + offset;
256
struct intel_batch_decode_bo bo = ctx_get_bo(ctx, true, state_addr);
257
const uint8_t *state_map = (const uint8_t *) bo.map;
258
259
if (state_map == NULL) {
260
ImGui::TextColored(ctx->cfg->missing_color,
261
"samplers unavailable addr=0x%012" PRIx64, state_addr);
262
return;
263
}
264
265
if (offset % 32 != 0) {
266
ImGui::TextColored(ctx->cfg->missing_color, "invalid sampler state pointer");
267
return;
268
}
269
270
const unsigned sampler_state_size = strct->dw_length * 4;
271
272
if (count * sampler_state_size >= bo.size) {
273
ImGui::TextColored(ctx->cfg->missing_color, "sampler state ends after bo ends");
274
return;
275
}
276
277
for (int i = 0; i < count; i++) {
278
if (ImGui::TreeNodeEx(state_map, ImGuiTreeNodeFlags_Framed,
279
"sampler state %d", i)) {
280
aub_viewer_print_group(ctx, strct, state_addr, state_map);
281
ImGui::TreePop();
282
}
283
state_addr += sampler_state_size;
284
state_map += sampler_state_size;
285
}
286
}
287
288
static void
289
handle_media_interface_descriptor_load(struct aub_viewer_decode_ctx *ctx,
290
struct intel_group *inst,
291
const uint32_t *p)
292
{
293
struct intel_group *desc =
294
intel_spec_find_struct(ctx->spec, "INTERFACE_DESCRIPTOR_DATA");
295
296
struct intel_field_iterator iter;
297
intel_field_iterator_init(&iter, inst, p, 0, false);
298
uint32_t descriptor_offset = 0;
299
int descriptor_count = 0;
300
while (intel_field_iterator_next(&iter)) {
301
if (strcmp(iter.name, "Interface Descriptor Data Start Address") == 0) {
302
descriptor_offset = strtol(iter.value, NULL, 16);
303
} else if (strcmp(iter.name, "Interface Descriptor Total Length") == 0) {
304
descriptor_count =
305
strtol(iter.value, NULL, 16) / (desc->dw_length * 4);
306
}
307
}
308
309
uint64_t desc_addr = ctx->dynamic_base + descriptor_offset;
310
struct intel_batch_decode_bo bo = ctx_get_bo(ctx, true, desc_addr);
311
const uint32_t *desc_map = (const uint32_t *) bo.map;
312
313
if (desc_map == NULL) {
314
ImGui::TextColored(ctx->cfg->missing_color,
315
"interface descriptors unavailable addr=0x%012" PRIx64, desc_addr);
316
return;
317
}
318
319
for (int i = 0; i < descriptor_count; i++) {
320
ImGui::Text("descriptor %d: %012x", i, descriptor_offset);
321
322
aub_viewer_print_group(ctx, desc, desc_addr, desc_map);
323
324
intel_field_iterator_init(&iter, desc, desc_map, 0, false);
325
uint64_t ksp = 0;
326
uint32_t sampler_offset = 0, sampler_count = 0;
327
uint32_t binding_table_offset = 0, binding_entry_count = 0;
328
while (intel_field_iterator_next(&iter)) {
329
if (strcmp(iter.name, "Kernel Start Pointer") == 0) {
330
ksp = strtoll(iter.value, NULL, 16);
331
} else if (strcmp(iter.name, "Sampler State Pointer") == 0) {
332
sampler_offset = strtol(iter.value, NULL, 16);
333
} else if (strcmp(iter.name, "Sampler Count") == 0) {
334
sampler_count = strtol(iter.value, NULL, 10);
335
} else if (strcmp(iter.name, "Binding Table Pointer") == 0) {
336
binding_table_offset = strtol(iter.value, NULL, 16);
337
} else if (strcmp(iter.name, "Binding Table Entry Count") == 0) {
338
binding_entry_count = strtol(iter.value, NULL, 10);
339
}
340
}
341
342
ctx_disassemble_program(ctx, ksp, "compute shader");
343
344
dump_samplers(ctx, sampler_offset, sampler_count);
345
dump_binding_table(ctx, binding_table_offset, binding_entry_count);
346
347
desc_map += desc->dw_length;
348
desc_addr += desc->dw_length * 4;
349
}
350
}
351
352
static void
353
handle_3dstate_vertex_buffers(struct aub_viewer_decode_ctx *ctx,
354
struct intel_group *inst,
355
const uint32_t *p)
356
{
357
struct intel_group *vbs = intel_spec_find_struct(ctx->spec, "VERTEX_BUFFER_STATE");
358
359
struct intel_batch_decode_bo vb = {};
360
uint32_t vb_size = 0;
361
int index = -1;
362
int pitch = -1;
363
bool ready = false;
364
365
struct intel_field_iterator iter;
366
intel_field_iterator_init(&iter, inst, p, 0, false);
367
while (intel_field_iterator_next(&iter)) {
368
if (iter.struct_desc != vbs)
369
continue;
370
371
uint64_t buffer_addr = 0;
372
373
struct intel_field_iterator vbs_iter;
374
intel_field_iterator_init(&vbs_iter, vbs, &iter.p[iter.start_bit / 32], 0, false);
375
while (intel_field_iterator_next(&vbs_iter)) {
376
if (strcmp(vbs_iter.name, "Vertex Buffer Index") == 0) {
377
index = vbs_iter.raw_value;
378
} else if (strcmp(vbs_iter.name, "Buffer Pitch") == 0) {
379
pitch = vbs_iter.raw_value;
380
} else if (strcmp(vbs_iter.name, "Buffer Starting Address") == 0) {
381
buffer_addr = vbs_iter.raw_value;
382
vb = ctx_get_bo(ctx, true, buffer_addr);
383
} else if (strcmp(vbs_iter.name, "Buffer Size") == 0) {
384
vb_size = vbs_iter.raw_value;
385
ready = true;
386
} else if (strcmp(vbs_iter.name, "End Address") == 0) {
387
if (vb.map && vbs_iter.raw_value >= vb.addr)
388
vb_size = vbs_iter.raw_value - vb.addr;
389
else
390
vb_size = 0;
391
ready = true;
392
}
393
394
if (!ready)
395
continue;
396
397
ImGui::Text("vertex buffer %d, size %d, pitch %d", index, vb_size, pitch);
398
399
if (vb.map == NULL) {
400
ImGui::TextColored(ctx->cfg->missing_color,
401
"buffer contents unavailable addr=0x%012" PRIx64, buffer_addr);
402
continue;
403
}
404
405
if (vb.map == 0 || vb_size == 0)
406
continue;
407
408
vb.map = NULL;
409
vb_size = 0;
410
index = -1;
411
pitch = -1;
412
ready = false;
413
}
414
}
415
}
416
417
static void
418
handle_3dstate_index_buffer(struct aub_viewer_decode_ctx *ctx,
419
struct intel_group *inst,
420
const uint32_t *p)
421
{
422
struct intel_batch_decode_bo ib = {};
423
uint64_t buffer_addr = 0;
424
uint32_t ib_size = 0;
425
uint32_t format = 0;
426
427
struct intel_field_iterator iter;
428
intel_field_iterator_init(&iter, inst, p, 0, false);
429
while (intel_field_iterator_next(&iter)) {
430
if (strcmp(iter.name, "Index Format") == 0) {
431
format = iter.raw_value;
432
} else if (strcmp(iter.name, "Buffer Starting Address") == 0) {
433
buffer_addr = iter.raw_value;
434
ib = ctx_get_bo(ctx, true, buffer_addr);
435
} else if (strcmp(iter.name, "Buffer Size") == 0) {
436
ib_size = iter.raw_value;
437
}
438
}
439
440
if (ib.map == NULL) {
441
ImGui::TextColored(ctx->cfg->missing_color,
442
"buffer contents unavailable addr=0x%012" PRIx64,
443
buffer_addr);
444
return;
445
}
446
447
const uint8_t *m = (const uint8_t *) ib.map;
448
const uint8_t *ib_end = m + MIN2(ib.size, ib_size);
449
for (int i = 0; m < ib_end && i < 10; i++) {
450
switch (format) {
451
case 0:
452
m += 1;
453
break;
454
case 1:
455
m += 2;
456
break;
457
case 2:
458
m += 4;
459
break;
460
}
461
}
462
}
463
464
static void
465
decode_single_ksp(struct aub_viewer_decode_ctx *ctx,
466
struct intel_group *inst,
467
const uint32_t *p)
468
{
469
uint64_t ksp = 0;
470
bool is_simd8 = false; /* vertex shaders on Gfx8+ only */
471
bool is_enabled = true;
472
473
struct intel_field_iterator iter;
474
intel_field_iterator_init(&iter, inst, p, 0, false);
475
while (intel_field_iterator_next(&iter)) {
476
if (strcmp(iter.name, "Kernel Start Pointer") == 0) {
477
ksp = iter.raw_value;
478
} else if (strcmp(iter.name, "SIMD8 Dispatch Enable") == 0) {
479
is_simd8 = iter.raw_value;
480
} else if (strcmp(iter.name, "Dispatch Mode") == 0) {
481
is_simd8 = strcmp(iter.value, "SIMD8") == 0;
482
} else if (strcmp(iter.name, "Dispatch Enable") == 0) {
483
is_simd8 = strcmp(iter.value, "SIMD8") == 0;
484
} else if (strcmp(iter.name, "Enable") == 0) {
485
is_enabled = iter.raw_value;
486
}
487
}
488
489
const char *type =
490
strcmp(inst->name, "VS_STATE") == 0 ? "vertex shader" :
491
strcmp(inst->name, "GS_STATE") == 0 ? "geometry shader" :
492
strcmp(inst->name, "SF_STATE") == 0 ? "strips and fans shader" :
493
strcmp(inst->name, "CLIP_STATE") == 0 ? "clip shader" :
494
strcmp(inst->name, "3DSTATE_DS") == 0 ? "tessellation evaluation shader" :
495
strcmp(inst->name, "3DSTATE_HS") == 0 ? "tessellation control shader" :
496
strcmp(inst->name, "3DSTATE_VS") == 0 ? (is_simd8 ? "SIMD8 vertex shader" : "vec4 vertex shader") :
497
strcmp(inst->name, "3DSTATE_GS") == 0 ? (is_simd8 ? "SIMD8 geometry shader" : "vec4 geometry shader") :
498
NULL;
499
500
if (is_enabled)
501
ctx_disassemble_program(ctx, ksp, type);
502
}
503
504
static void
505
decode_ps_kernels(struct aub_viewer_decode_ctx *ctx,
506
struct intel_group *inst,
507
const uint32_t *p)
508
{
509
uint64_t ksp[3] = {0, 0, 0};
510
bool enabled[3] = {false, false, false};
511
512
struct intel_field_iterator iter;
513
intel_field_iterator_init(&iter, inst, p, 0, false);
514
while (intel_field_iterator_next(&iter)) {
515
if (strncmp(iter.name, "Kernel Start Pointer ",
516
strlen("Kernel Start Pointer ")) == 0) {
517
int idx = iter.name[strlen("Kernel Start Pointer ")] - '0';
518
ksp[idx] = strtol(iter.value, NULL, 16);
519
} else if (strcmp(iter.name, "8 Pixel Dispatch Enable") == 0) {
520
enabled[0] = strcmp(iter.value, "true") == 0;
521
} else if (strcmp(iter.name, "16 Pixel Dispatch Enable") == 0) {
522
enabled[1] = strcmp(iter.value, "true") == 0;
523
} else if (strcmp(iter.name, "32 Pixel Dispatch Enable") == 0) {
524
enabled[2] = strcmp(iter.value, "true") == 0;
525
}
526
}
527
528
/* Reorder KSPs to be [8, 16, 32] instead of the hardware order. */
529
if (enabled[0] + enabled[1] + enabled[2] == 1) {
530
if (enabled[1]) {
531
ksp[1] = ksp[0];
532
ksp[0] = 0;
533
} else if (enabled[2]) {
534
ksp[2] = ksp[0];
535
ksp[0] = 0;
536
}
537
} else {
538
uint64_t tmp = ksp[1];
539
ksp[1] = ksp[2];
540
ksp[2] = tmp;
541
}
542
543
if (enabled[0])
544
ctx_disassemble_program(ctx, ksp[0], "SIMD8 fragment shader");
545
if (enabled[1])
546
ctx_disassemble_program(ctx, ksp[1], "SIMD16 fragment shader");
547
if (enabled[2])
548
ctx_disassemble_program(ctx, ksp[2], "SIMD32 fragment shader");
549
}
550
551
static void
552
decode_3dstate_constant(struct aub_viewer_decode_ctx *ctx,
553
struct intel_group *inst,
554
const uint32_t *p)
555
{
556
struct intel_group *body =
557
intel_spec_find_struct(ctx->spec, "3DSTATE_CONSTANT_BODY");
558
559
uint32_t read_length[4] = {0};
560
uint64_t read_addr[4];
561
562
struct intel_field_iterator outer;
563
intel_field_iterator_init(&outer, inst, p, 0, false);
564
while (intel_field_iterator_next(&outer)) {
565
if (outer.struct_desc != body)
566
continue;
567
568
struct intel_field_iterator iter;
569
intel_field_iterator_init(&iter, body, &outer.p[outer.start_bit / 32],
570
0, false);
571
572
while (intel_field_iterator_next(&iter)) {
573
int idx;
574
if (sscanf(iter.name, "Read Length[%d]", &idx) == 1) {
575
read_length[idx] = iter.raw_value;
576
} else if (sscanf(iter.name, "Buffer[%d]", &idx) == 1) {
577
read_addr[idx] = iter.raw_value;
578
}
579
}
580
581
for (int i = 0; i < 4; i++) {
582
if (read_length[i] == 0)
583
continue;
584
585
struct intel_batch_decode_bo buffer = ctx_get_bo(ctx, true, read_addr[i]);
586
if (!buffer.map) {
587
ImGui::TextColored(ctx->cfg->missing_color,
588
"constant buffer %d unavailable addr=0x%012" PRIx64,
589
i, read_addr[i]);
590
continue;
591
}
592
593
unsigned size = read_length[i] * 32;
594
ImGui::Text("constant buffer %d, size %u", i, size);
595
596
if (ctx->edit_address) {
597
if (ImGui::Button("Show/Edit buffer"))
598
ctx->edit_address(ctx->user_data, read_addr[i], size);
599
}
600
}
601
}
602
}
603
604
static void
605
decode_3dstate_binding_table_pointers(struct aub_viewer_decode_ctx *ctx,
606
struct intel_group *inst,
607
const uint32_t *p)
608
{
609
dump_binding_table(ctx, p[1], -1);
610
}
611
612
static void
613
decode_3dstate_sampler_state_pointers(struct aub_viewer_decode_ctx *ctx,
614
struct intel_group *inst,
615
const uint32_t *p)
616
{
617
dump_samplers(ctx, p[1], 1);
618
}
619
620
static void
621
decode_3dstate_sampler_state_pointers_gfx6(struct aub_viewer_decode_ctx *ctx,
622
struct intel_group *inst,
623
const uint32_t *p)
624
{
625
dump_samplers(ctx, p[1], 1);
626
dump_samplers(ctx, p[2], 1);
627
dump_samplers(ctx, p[3], 1);
628
}
629
630
static bool
631
str_ends_with(const char *str, const char *end)
632
{
633
int offset = strlen(str) - strlen(end);
634
if (offset < 0)
635
return false;
636
637
return strcmp(str + offset, end) == 0;
638
}
639
640
static void
641
decode_dynamic_state_pointers(struct aub_viewer_decode_ctx *ctx,
642
struct intel_group *inst, const uint32_t *p,
643
const char *struct_type, int count)
644
{
645
uint32_t state_offset = 0;
646
647
struct intel_field_iterator iter;
648
intel_field_iterator_init(&iter, inst, p, 0, false);
649
while (intel_field_iterator_next(&iter)) {
650
if (str_ends_with(iter.name, "Pointer")) {
651
state_offset = iter.raw_value;
652
break;
653
}
654
}
655
656
uint64_t state_addr = ctx->dynamic_base + state_offset;
657
struct intel_batch_decode_bo bo = ctx_get_bo(ctx, true, state_addr);
658
const uint8_t *state_map = (const uint8_t *) bo.map;
659
660
if (state_map == NULL) {
661
ImGui::TextColored(ctx->cfg->missing_color,
662
"dynamic %s state unavailable addr=0x%012" PRIx64,
663
struct_type, state_addr);
664
return;
665
}
666
667
struct intel_group *state = intel_spec_find_struct(ctx->spec, struct_type);
668
if (strcmp(struct_type, "BLEND_STATE") == 0) {
669
/* Blend states are different from the others because they have a header
670
* struct called BLEND_STATE which is followed by a variable number of
671
* BLEND_STATE_ENTRY structs.
672
*/
673
ImGui::Text("%s", struct_type);
674
aub_viewer_print_group(ctx, state, state_addr, state_map);
675
676
state_addr += state->dw_length * 4;
677
state_map += state->dw_length * 4;
678
679
struct_type = "BLEND_STATE_ENTRY";
680
state = intel_spec_find_struct(ctx->spec, struct_type);
681
}
682
683
for (int i = 0; i < count; i++) {
684
ImGui::Text("%s %d", struct_type, i);
685
aub_viewer_print_group(ctx, state, state_addr, state_map);
686
687
state_addr += state->dw_length * 4;
688
state_map += state->dw_length * 4;
689
}
690
}
691
692
static void
693
decode_3dstate_viewport_state_pointers_cc(struct aub_viewer_decode_ctx *ctx,
694
struct intel_group *inst,
695
const uint32_t *p)
696
{
697
decode_dynamic_state_pointers(ctx, inst, p, "CC_VIEWPORT", 4);
698
}
699
700
static void
701
decode_3dstate_viewport_state_pointers_sf_clip(struct aub_viewer_decode_ctx *ctx,
702
struct intel_group *inst,
703
const uint32_t *p)
704
{
705
decode_dynamic_state_pointers(ctx, inst, p, "SF_CLIP_VIEWPORT", 4);
706
}
707
708
static void
709
decode_3dstate_blend_state_pointers(struct aub_viewer_decode_ctx *ctx,
710
struct intel_group *inst,
711
const uint32_t *p)
712
{
713
decode_dynamic_state_pointers(ctx, inst, p, "BLEND_STATE", 1);
714
}
715
716
static void
717
decode_3dstate_cc_state_pointers(struct aub_viewer_decode_ctx *ctx,
718
struct intel_group *inst,
719
const uint32_t *p)
720
{
721
decode_dynamic_state_pointers(ctx, inst, p, "COLOR_CALC_STATE", 1);
722
}
723
724
static void
725
decode_3dstate_scissor_state_pointers(struct aub_viewer_decode_ctx *ctx,
726
struct intel_group *inst,
727
const uint32_t *p)
728
{
729
decode_dynamic_state_pointers(ctx, inst, p, "SCISSOR_RECT", 1);
730
}
731
732
static void
733
decode_load_register_imm(struct aub_viewer_decode_ctx *ctx,
734
struct intel_group *inst,
735
const uint32_t *p)
736
{
737
struct intel_group *reg = intel_spec_find_register(ctx->spec, p[1]);
738
739
if (reg != NULL &&
740
ImGui::TreeNodeEx(&p[1], ImGuiTreeNodeFlags_Framed,
741
"%s (0x%x) = 0x%x",
742
reg->name, reg->register_offset, p[2])) {
743
aub_viewer_print_group(ctx, reg, reg->register_offset, &p[2]);
744
ImGui::TreePop();
745
}
746
}
747
748
static void
749
decode_3dprimitive(struct aub_viewer_decode_ctx *ctx,
750
struct intel_group *inst,
751
const uint32_t *p)
752
{
753
if (ctx->display_urb) {
754
if (ImGui::Button("Show URB"))
755
ctx->display_urb(ctx->user_data, ctx->urb_stages);
756
}
757
}
758
759
static void
760
handle_urb(struct aub_viewer_decode_ctx *ctx,
761
struct intel_group *inst,
762
const uint32_t *p)
763
{
764
struct intel_field_iterator iter;
765
intel_field_iterator_init(&iter, inst, p, 0, false);
766
while (intel_field_iterator_next(&iter)) {
767
if (strstr(iter.name, "URB Starting Address")) {
768
ctx->urb_stages[ctx->stage].start = iter.raw_value * 8192;
769
} else if (strstr(iter.name, "URB Entry Allocation Size")) {
770
ctx->urb_stages[ctx->stage].size = (iter.raw_value + 1) * 64;
771
} else if (strstr(iter.name, "Number of URB Entries")) {
772
ctx->urb_stages[ctx->stage].n_entries = iter.raw_value;
773
}
774
}
775
776
ctx->end_urb_offset = MAX2(ctx->urb_stages[ctx->stage].start +
777
ctx->urb_stages[ctx->stage].n_entries *
778
ctx->urb_stages[ctx->stage].size,
779
ctx->end_urb_offset);
780
}
781
782
static void
783
handle_urb_read(struct aub_viewer_decode_ctx *ctx,
784
struct intel_group *inst,
785
const uint32_t *p)
786
{
787
struct intel_field_iterator iter;
788
intel_field_iterator_init(&iter, inst, p, 0, false);
789
while (intel_field_iterator_next(&iter)) {
790
/* Workaround the "Force * URB Entry Read Length" fields */
791
if (iter.end_bit - iter.start_bit < 2)
792
continue;
793
794
if (strstr(iter.name, "URB Entry Read Offset")) {
795
ctx->urb_stages[ctx->stage].rd_offset = iter.raw_value * 32;
796
} else if (strstr(iter.name, "URB Entry Read Length")) {
797
ctx->urb_stages[ctx->stage].rd_length = iter.raw_value * 32;
798
} else if (strstr(iter.name, "URB Entry Output Read Offset")) {
799
ctx->urb_stages[ctx->stage].wr_offset = iter.raw_value * 32;
800
} else if (strstr(iter.name, "URB Entry Output Length")) {
801
ctx->urb_stages[ctx->stage].wr_length = iter.raw_value * 32;
802
}
803
}
804
}
805
806
static void
807
handle_urb_constant(struct aub_viewer_decode_ctx *ctx,
808
struct intel_group *inst,
809
const uint32_t *p)
810
{
811
struct intel_group *body =
812
intel_spec_find_struct(ctx->spec, "3DSTATE_CONSTANT_BODY");
813
814
struct intel_field_iterator outer;
815
intel_field_iterator_init(&outer, inst, p, 0, false);
816
while (intel_field_iterator_next(&outer)) {
817
if (outer.struct_desc != body)
818
continue;
819
820
struct intel_field_iterator iter;
821
intel_field_iterator_init(&iter, body, &outer.p[outer.start_bit / 32],
822
0, false);
823
824
ctx->urb_stages[ctx->stage].const_rd_length = 0;
825
while (intel_field_iterator_next(&iter)) {
826
int idx;
827
if (sscanf(iter.name, "Read Length[%d]", &idx) == 1) {
828
ctx->urb_stages[ctx->stage].const_rd_length += iter.raw_value * 32;
829
}
830
}
831
}
832
}
833
834
struct custom_decoder {
835
const char *cmd_name;
836
void (*decode)(struct aub_viewer_decode_ctx *ctx,
837
struct intel_group *inst,
838
const uint32_t *p);
839
enum aub_decode_stage stage;
840
} display_decoders[] = {
841
{ "STATE_BASE_ADDRESS", handle_state_base_address },
842
{ "MEDIA_INTERFACE_DESCRIPTOR_LOAD", handle_media_interface_descriptor_load },
843
{ "3DSTATE_VERTEX_BUFFERS", handle_3dstate_vertex_buffers },
844
{ "3DSTATE_INDEX_BUFFER", handle_3dstate_index_buffer },
845
{ "3DSTATE_VS", decode_single_ksp, AUB_DECODE_STAGE_VS, },
846
{ "3DSTATE_GS", decode_single_ksp, AUB_DECODE_STAGE_GS, },
847
{ "3DSTATE_DS", decode_single_ksp, AUB_DECODE_STAGE_DS, },
848
{ "3DSTATE_HS", decode_single_ksp, AUB_DECODE_STAGE_HS, },
849
{ "3DSTATE_PS", decode_ps_kernels, AUB_DECODE_STAGE_PS, },
850
{ "3DSTATE_CONSTANT_VS", decode_3dstate_constant, AUB_DECODE_STAGE_VS, },
851
{ "3DSTATE_CONSTANT_GS", decode_3dstate_constant, AUB_DECODE_STAGE_GS, },
852
{ "3DSTATE_CONSTANT_DS", decode_3dstate_constant, AUB_DECODE_STAGE_DS, },
853
{ "3DSTATE_CONSTANT_HS", decode_3dstate_constant, AUB_DECODE_STAGE_HS, },
854
{ "3DSTATE_CONSTANT_PS", decode_3dstate_constant, AUB_DECODE_STAGE_PS, },
855
856
{ "3DSTATE_BINDING_TABLE_POINTERS_VS", decode_3dstate_binding_table_pointers, AUB_DECODE_STAGE_VS, },
857
{ "3DSTATE_BINDING_TABLE_POINTERS_GS", decode_3dstate_binding_table_pointers, AUB_DECODE_STAGE_GS, },
858
{ "3DSTATE_BINDING_TABLE_POINTERS_HS", decode_3dstate_binding_table_pointers, AUB_DECODE_STAGE_HS, },
859
{ "3DSTATE_BINDING_TABLE_POINTERS_DS", decode_3dstate_binding_table_pointers, AUB_DECODE_STAGE_DS, },
860
{ "3DSTATE_BINDING_TABLE_POINTERS_PS", decode_3dstate_binding_table_pointers, AUB_DECODE_STAGE_PS, },
861
862
{ "3DSTATE_SAMPLER_STATE_POINTERS_VS", decode_3dstate_sampler_state_pointers, AUB_DECODE_STAGE_VS, },
863
{ "3DSTATE_SAMPLER_STATE_POINTERS_GS", decode_3dstate_sampler_state_pointers, AUB_DECODE_STAGE_GS, },
864
{ "3DSTATE_SAMPLER_STATE_POINTERS_DS", decode_3dstate_sampler_state_pointers, AUB_DECODE_STAGE_DS, },
865
{ "3DSTATE_SAMPLER_STATE_POINTERS_HS", decode_3dstate_sampler_state_pointers, AUB_DECODE_STAGE_HS, },
866
{ "3DSTATE_SAMPLER_STATE_POINTERS_PS", decode_3dstate_sampler_state_pointers, AUB_DECODE_STAGE_PS, },
867
{ "3DSTATE_SAMPLER_STATE_POINTERS", decode_3dstate_sampler_state_pointers_gfx6 },
868
869
{ "3DSTATE_VIEWPORT_STATE_POINTERS_CC", decode_3dstate_viewport_state_pointers_cc },
870
{ "3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP", decode_3dstate_viewport_state_pointers_sf_clip },
871
{ "3DSTATE_BLEND_STATE_POINTERS", decode_3dstate_blend_state_pointers },
872
{ "3DSTATE_CC_STATE_POINTERS", decode_3dstate_cc_state_pointers },
873
{ "3DSTATE_SCISSOR_STATE_POINTERS", decode_3dstate_scissor_state_pointers },
874
{ "MI_LOAD_REGISTER_IMM", decode_load_register_imm },
875
{ "3DPRIMITIVE", decode_3dprimitive },
876
};
877
878
struct custom_decoder info_decoders[] = {
879
{ "STATE_BASE_ADDRESS", handle_state_base_address },
880
{ "3DSTATE_URB_VS", handle_urb, AUB_DECODE_STAGE_VS, },
881
{ "3DSTATE_URB_GS", handle_urb, AUB_DECODE_STAGE_GS, },
882
{ "3DSTATE_URB_DS", handle_urb, AUB_DECODE_STAGE_DS, },
883
{ "3DSTATE_URB_HS", handle_urb, AUB_DECODE_STAGE_HS, },
884
{ "3DSTATE_VS", handle_urb_read, AUB_DECODE_STAGE_VS, },
885
{ "3DSTATE_GS", handle_urb_read, AUB_DECODE_STAGE_GS, },
886
{ "3DSTATE_DS", handle_urb_read, AUB_DECODE_STAGE_DS, },
887
{ "3DSTATE_HS", handle_urb_read, AUB_DECODE_STAGE_HS, },
888
{ "3DSTATE_PS", handle_urb_read, AUB_DECODE_STAGE_PS, },
889
{ "3DSTATE_CONSTANT_VS", handle_urb_constant, AUB_DECODE_STAGE_VS, },
890
{ "3DSTATE_CONSTANT_GS", handle_urb_constant, AUB_DECODE_STAGE_GS, },
891
{ "3DSTATE_CONSTANT_DS", handle_urb_constant, AUB_DECODE_STAGE_DS, },
892
{ "3DSTATE_CONSTANT_HS", handle_urb_constant, AUB_DECODE_STAGE_HS, },
893
{ "3DSTATE_CONSTANT_PS", handle_urb_constant, AUB_DECODE_STAGE_PS, },
894
};
895
896
void
897
aub_viewer_render_batch(struct aub_viewer_decode_ctx *ctx,
898
const void *_batch, uint32_t batch_size,
899
uint64_t batch_addr, bool from_ring)
900
{
901
struct intel_group *inst;
902
const uint32_t *p, *batch = (const uint32_t *) _batch, *end = batch + batch_size / sizeof(uint32_t);
903
int length;
904
905
if (ctx->n_batch_buffer_start >= 100) {
906
ImGui::TextColored(ctx->cfg->error_color,
907
"0x%08" PRIx64 ": Max batch buffer jumps exceeded", batch_addr);
908
return;
909
}
910
911
ctx->n_batch_buffer_start++;
912
913
for (p = batch; p < end; p += length) {
914
inst = intel_spec_find_instruction(ctx->spec, ctx->engine, p);
915
length = intel_group_get_length(inst, p);
916
assert(inst == NULL || length > 0);
917
length = MAX2(1, length);
918
919
uint64_t offset = batch_addr + ((char *)p - (char *)batch);
920
921
if (inst == NULL) {
922
ImGui::TextColored(ctx->cfg->error_color,
923
"0x%012" PRIx64 ": unknown instruction %012x",
924
offset, p[0]);
925
continue;
926
}
927
928
const char *inst_name = intel_group_get_name(inst);
929
930
for (unsigned i = 0; i < ARRAY_SIZE(info_decoders); i++) {
931
if (strcmp(inst_name, info_decoders[i].cmd_name) == 0) {
932
ctx->stage = info_decoders[i].stage;
933
info_decoders[i].decode(ctx, inst, p);
934
break;
935
}
936
}
937
938
if (ctx->decode_cfg->command_filter.PassFilter(inst->name) &&
939
ImGui::TreeNodeEx(p,
940
ImGuiTreeNodeFlags_Framed,
941
"0x%012" PRIx64 ": %s",
942
offset, inst->name)) {
943
aub_viewer_print_group(ctx, inst, offset, p);
944
945
for (unsigned i = 0; i < ARRAY_SIZE(display_decoders); i++) {
946
if (strcmp(inst_name, display_decoders[i].cmd_name) == 0) {
947
ctx->stage = display_decoders[i].stage;
948
display_decoders[i].decode(ctx, inst, p);
949
break;
950
}
951
}
952
953
if (ctx->edit_address) {
954
if (ImGui::Button("Edit instruction"))
955
ctx->edit_address(ctx->user_data, offset, length * 4);
956
}
957
958
ImGui::TreePop();
959
}
960
961
if (strcmp(inst_name, "MI_BATCH_BUFFER_START") == 0) {
962
uint64_t next_batch_addr = 0xd0d0d0d0;
963
bool ppgtt = false;
964
bool second_level = false;
965
struct intel_field_iterator iter;
966
intel_field_iterator_init(&iter, inst, p, 0, false);
967
while (intel_field_iterator_next(&iter)) {
968
if (strcmp(iter.name, "Batch Buffer Start Address") == 0) {
969
next_batch_addr = iter.raw_value;
970
} else if (strcmp(iter.name, "Second Level Batch Buffer") == 0) {
971
second_level = iter.raw_value;
972
} else if (strcmp(iter.name, "Address Space Indicator") == 0) {
973
ppgtt = iter.raw_value;
974
}
975
}
976
977
struct intel_batch_decode_bo next_batch = ctx_get_bo(ctx, ppgtt, next_batch_addr);
978
979
if (next_batch.map == NULL) {
980
ImGui::TextColored(ctx->cfg->missing_color,
981
"Secondary batch at 0x%012" PRIx64 " unavailable",
982
next_batch_addr);
983
} else {
984
aub_viewer_render_batch(ctx, next_batch.map, next_batch.size,
985
next_batch.addr, false);
986
}
987
if (second_level) {
988
/* MI_BATCH_BUFFER_START with "2nd Level Batch Buffer" set acts
989
* like a subroutine call. Commands that come afterwards get
990
* processed once the 2nd level batch buffer returns with
991
* MI_BATCH_BUFFER_END.
992
*/
993
continue;
994
} else if (!from_ring) {
995
/* MI_BATCH_BUFFER_START with "2nd Level Batch Buffer" unset acts
996
* like a goto. Nothing after it will ever get processed. In
997
* order to prevent the recursion from growing, we just reset the
998
* loop and continue;
999
*/
1000
break;
1001
}
1002
} else if (strcmp(inst_name, "MI_BATCH_BUFFER_END") == 0) {
1003
break;
1004
}
1005
}
1006
1007
ctx->n_batch_buffer_start--;
1008
}
1009
1010