• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
aub_viewer_decode_ctx_init(struct aub_viewer_decode_ctx * ctx,struct aub_viewer_cfg * cfg,struct aub_viewer_decode_cfg * decode_cfg,const struct gen_device_info * devinfo,struct gen_spec * spec,struct gen_batch_decode_bo (* get_bo)(void *,bool,uint64_t),unsigned (* get_state_size)(void *,uint32_t),void * user_data)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 gen_device_info *devinfo,
35                            struct gen_spec *spec,
36                            struct gen_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
aub_viewer_print_group(struct aub_viewer_decode_ctx * ctx,struct gen_group * group,uint64_t address,const void * map)54 aub_viewer_print_group(struct aub_viewer_decode_ctx *ctx,
55                        struct gen_group *group,
56                        uint64_t address, const void *map)
57 {
58    struct gen_field_iterator iter;
59    int last_dword = -1;
60    const uint32_t *p = (const uint32_t *) map;
61 
62    gen_field_iterator_init(&iter, group, p, 0, false);
63    while (gen_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 (!gen_field_is_header(iter.field)) {
76          if (ctx->decode_cfg->field_filter.PassFilter(iter.name)) {
77             if (iter.field->type.kind == gen_type::GEN_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 gen_batch_decode_bo
ctx_get_bo(struct aub_viewer_decode_ctx * ctx,bool ppgtt,uint64_t addr)95 ctx_get_bo(struct aub_viewer_decode_ctx *ctx, bool ppgtt, uint64_t addr)
96 {
97    if (gen_spec_get_gen(ctx->spec) >= gen_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 gen_batch_decode_bo bo = ctx->get_bo(ctx->user_data, ppgtt, addr);
108 
109    if (gen_spec_get_gen(ctx->spec) >= gen_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
update_count(struct aub_viewer_decode_ctx * ctx,uint32_t offset_from_dsba,unsigned element_dwords,unsigned guess)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
ctx_disassemble_program(struct aub_viewer_decode_ctx * ctx,uint32_t ksp,const char * type)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 gen_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
handle_state_base_address(struct aub_viewer_decode_ctx * ctx,struct gen_group * inst,const uint32_t * p)161 handle_state_base_address(struct aub_viewer_decode_ctx *ctx,
162                           struct gen_group *inst,
163                           const uint32_t *p)
164 {
165    struct gen_field_iterator iter;
166    gen_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 (gen_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
dump_binding_table(struct aub_viewer_decode_ctx * ctx,uint32_t offset,int count)198 dump_binding_table(struct aub_viewer_decode_ctx *ctx, uint32_t offset, int count)
199 {
200    struct gen_group *strct =
201       gen_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 gen_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 gen_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
dump_samplers(struct aub_viewer_decode_ctx * ctx,uint32_t offset,int count)251 dump_samplers(struct aub_viewer_decode_ctx *ctx, uint32_t offset, int count)
252 {
253    struct gen_group *strct = gen_spec_find_struct(ctx->spec, "SAMPLER_STATE");
254 
255    if (count < 0)
256       count = update_count(ctx, offset, strct->dw_length, 4);
257 
258    uint64_t state_addr = ctx->dynamic_base + offset;
259    struct gen_batch_decode_bo bo = ctx_get_bo(ctx, true, state_addr);
260    const uint8_t *state_map = (const uint8_t *) bo.map;
261 
262    if (state_map == NULL) {
263       ImGui::TextColored(ctx->cfg->missing_color,
264                          "samplers unavailable addr=0x%012" PRIx64, state_addr);
265       return;
266    }
267 
268    if (offset % 32 != 0 || state_addr - bo.addr >= bo.size) {
269       ImGui::TextColored(ctx->cfg->missing_color, "invalid sampler state pointer");
270       return;
271    }
272 
273    for (int i = 0; i < count; i++) {
274       if (ImGui::TreeNodeEx(state_map, ImGuiTreeNodeFlags_Framed,
275                             "sampler state %d", i)) {
276          aub_viewer_print_group(ctx, strct, state_addr, state_map);
277          ImGui::TreePop();
278       }
279       state_addr += 16;
280       state_map += 16;
281    }
282 }
283 
284 static void
handle_media_interface_descriptor_load(struct aub_viewer_decode_ctx * ctx,struct gen_group * inst,const uint32_t * p)285 handle_media_interface_descriptor_load(struct aub_viewer_decode_ctx *ctx,
286                                        struct gen_group *inst,
287                                        const uint32_t *p)
288 {
289    struct gen_group *desc =
290       gen_spec_find_struct(ctx->spec, "INTERFACE_DESCRIPTOR_DATA");
291 
292    struct gen_field_iterator iter;
293    gen_field_iterator_init(&iter, inst, p, 0, false);
294    uint32_t descriptor_offset = 0;
295    int descriptor_count = 0;
296    while (gen_field_iterator_next(&iter)) {
297       if (strcmp(iter.name, "Interface Descriptor Data Start Address") == 0) {
298          descriptor_offset = strtol(iter.value, NULL, 16);
299       } else if (strcmp(iter.name, "Interface Descriptor Total Length") == 0) {
300          descriptor_count =
301             strtol(iter.value, NULL, 16) / (desc->dw_length * 4);
302       }
303    }
304 
305    uint64_t desc_addr = ctx->dynamic_base + descriptor_offset;
306    struct gen_batch_decode_bo bo = ctx_get_bo(ctx, true, desc_addr);
307    const uint32_t *desc_map = (const uint32_t *) bo.map;
308 
309    if (desc_map == NULL) {
310       ImGui::TextColored(ctx->cfg->missing_color,
311                          "interface descriptors unavailable addr=0x%012" PRIx64, desc_addr);
312       return;
313    }
314 
315    for (int i = 0; i < descriptor_count; i++) {
316       ImGui::Text("descriptor %d: %012x", i, descriptor_offset);
317 
318       aub_viewer_print_group(ctx, desc, desc_addr, desc_map);
319 
320       gen_field_iterator_init(&iter, desc, desc_map, 0, false);
321       uint64_t ksp = 0;
322       uint32_t sampler_offset = 0, sampler_count = 0;
323       uint32_t binding_table_offset = 0, binding_entry_count = 0;
324       while (gen_field_iterator_next(&iter)) {
325          if (strcmp(iter.name, "Kernel Start Pointer") == 0) {
326             ksp = strtoll(iter.value, NULL, 16);
327          } else if (strcmp(iter.name, "Sampler State Pointer") == 0) {
328             sampler_offset = strtol(iter.value, NULL, 16);
329          } else if (strcmp(iter.name, "Sampler Count") == 0) {
330             sampler_count = strtol(iter.value, NULL, 10);
331          } else if (strcmp(iter.name, "Binding Table Pointer") == 0) {
332             binding_table_offset = strtol(iter.value, NULL, 16);
333          } else if (strcmp(iter.name, "Binding Table Entry Count") == 0) {
334             binding_entry_count = strtol(iter.value, NULL, 10);
335          }
336       }
337 
338       ctx_disassemble_program(ctx, ksp, "compute shader");
339 
340       dump_samplers(ctx, sampler_offset, sampler_count);
341       dump_binding_table(ctx, binding_table_offset, binding_entry_count);
342 
343       desc_map += desc->dw_length;
344       desc_addr += desc->dw_length * 4;
345    }
346 }
347 
348 static void
handle_3dstate_vertex_buffers(struct aub_viewer_decode_ctx * ctx,struct gen_group * inst,const uint32_t * p)349 handle_3dstate_vertex_buffers(struct aub_viewer_decode_ctx *ctx,
350                               struct gen_group *inst,
351                               const uint32_t *p)
352 {
353    struct gen_group *vbs = gen_spec_find_struct(ctx->spec, "VERTEX_BUFFER_STATE");
354 
355    struct gen_batch_decode_bo vb = {};
356    uint32_t vb_size = 0;
357    int index = -1;
358    int pitch = -1;
359    bool ready = false;
360 
361    struct gen_field_iterator iter;
362    gen_field_iterator_init(&iter, inst, p, 0, false);
363    while (gen_field_iterator_next(&iter)) {
364       if (iter.struct_desc != vbs)
365          continue;
366 
367       uint64_t buffer_addr = 0;
368 
369       struct gen_field_iterator vbs_iter;
370       gen_field_iterator_init(&vbs_iter, vbs, &iter.p[iter.start_bit / 32], 0, false);
371       while (gen_field_iterator_next(&vbs_iter)) {
372          if (strcmp(vbs_iter.name, "Vertex Buffer Index") == 0) {
373             index = vbs_iter.raw_value;
374          } else if (strcmp(vbs_iter.name, "Buffer Pitch") == 0) {
375             pitch = vbs_iter.raw_value;
376          } else if (strcmp(vbs_iter.name, "Buffer Starting Address") == 0) {
377             buffer_addr = vbs_iter.raw_value;
378             vb = ctx_get_bo(ctx, true, buffer_addr);
379          } else if (strcmp(vbs_iter.name, "Buffer Size") == 0) {
380             vb_size = vbs_iter.raw_value;
381             ready = true;
382          } else if (strcmp(vbs_iter.name, "End Address") == 0) {
383             if (vb.map && vbs_iter.raw_value >= vb.addr)
384                vb_size = vbs_iter.raw_value - vb.addr;
385             else
386                vb_size = 0;
387             ready = true;
388          }
389 
390          if (!ready)
391             continue;
392 
393          ImGui::Text("vertex buffer %d, size %d, pitch %d", index, vb_size, pitch);
394 
395          if (vb.map == NULL) {
396             ImGui::TextColored(ctx->cfg->missing_color,
397                                "buffer contents unavailable addr=0x%012" PRIx64, buffer_addr);
398             continue;
399          }
400 
401          if (vb.map == 0 || vb_size == 0)
402             continue;
403 
404          vb.map = NULL;
405          vb_size = 0;
406          index = -1;
407          pitch = -1;
408          ready = false;
409       }
410    }
411 }
412 
413 static void
handle_3dstate_index_buffer(struct aub_viewer_decode_ctx * ctx,struct gen_group * inst,const uint32_t * p)414 handle_3dstate_index_buffer(struct aub_viewer_decode_ctx *ctx,
415                             struct gen_group *inst,
416                             const uint32_t *p)
417 {
418    struct gen_batch_decode_bo ib = {};
419    uint64_t buffer_addr = 0;
420    uint32_t ib_size = 0;
421    uint32_t format = 0;
422 
423    struct gen_field_iterator iter;
424    gen_field_iterator_init(&iter, inst, p, 0, false);
425    while (gen_field_iterator_next(&iter)) {
426       if (strcmp(iter.name, "Index Format") == 0) {
427          format = iter.raw_value;
428       } else if (strcmp(iter.name, "Buffer Starting Address") == 0) {
429          buffer_addr = iter.raw_value;
430          ib = ctx_get_bo(ctx, true, buffer_addr);
431       } else if (strcmp(iter.name, "Buffer Size") == 0) {
432          ib_size = iter.raw_value;
433       }
434    }
435 
436    if (ib.map == NULL) {
437       ImGui::TextColored(ctx->cfg->missing_color,
438                          "buffer contents unavailable addr=0x%012" PRIx64,
439                          buffer_addr);
440       return;
441    }
442 
443    const uint8_t *m = (const uint8_t *) ib.map;
444    const uint8_t *ib_end = m + MIN2(ib.size, ib_size);
445    for (int i = 0; m < ib_end && i < 10; i++) {
446       switch (format) {
447       case 0:
448          m += 1;
449          break;
450       case 1:
451          m += 2;
452          break;
453       case 2:
454          m += 4;
455          break;
456       }
457    }
458 }
459 
460 static void
decode_single_ksp(struct aub_viewer_decode_ctx * ctx,struct gen_group * inst,const uint32_t * p)461 decode_single_ksp(struct aub_viewer_decode_ctx *ctx,
462                   struct gen_group *inst,
463                   const uint32_t *p)
464 {
465    uint64_t ksp = 0;
466    bool is_simd8 = false; /* vertex shaders on Gen8+ only */
467    bool is_enabled = true;
468 
469    struct gen_field_iterator iter;
470    gen_field_iterator_init(&iter, inst, p, 0, false);
471    while (gen_field_iterator_next(&iter)) {
472       if (strcmp(iter.name, "Kernel Start Pointer") == 0) {
473          ksp = iter.raw_value;
474       } else if (strcmp(iter.name, "SIMD8 Dispatch Enable") == 0) {
475          is_simd8 = iter.raw_value;
476       } else if (strcmp(iter.name, "Dispatch Mode") == 0) {
477          is_simd8 = strcmp(iter.value, "SIMD8") == 0;
478       } else if (strcmp(iter.name, "Dispatch Enable") == 0) {
479          is_simd8 = strcmp(iter.value, "SIMD8") == 0;
480       } else if (strcmp(iter.name, "Enable") == 0) {
481          is_enabled = iter.raw_value;
482       }
483    }
484 
485    const char *type =
486       strcmp(inst->name,   "VS_STATE") == 0 ? "vertex shader" :
487       strcmp(inst->name,   "GS_STATE") == 0 ? "geometry shader" :
488       strcmp(inst->name,   "SF_STATE") == 0 ? "strips and fans shader" :
489       strcmp(inst->name, "CLIP_STATE") == 0 ? "clip shader" :
490       strcmp(inst->name, "3DSTATE_DS") == 0 ? "tessellation evaluation shader" :
491       strcmp(inst->name, "3DSTATE_HS") == 0 ? "tessellation control shader" :
492       strcmp(inst->name, "3DSTATE_VS") == 0 ? (is_simd8 ? "SIMD8 vertex shader" : "vec4 vertex shader") :
493       strcmp(inst->name, "3DSTATE_GS") == 0 ? (is_simd8 ? "SIMD8 geometry shader" : "vec4 geometry shader") :
494       NULL;
495 
496    if (is_enabled)
497       ctx_disassemble_program(ctx, ksp, type);
498 }
499 
500 static void
decode_ps_kernels(struct aub_viewer_decode_ctx * ctx,struct gen_group * inst,const uint32_t * p)501 decode_ps_kernels(struct aub_viewer_decode_ctx *ctx,
502                   struct gen_group *inst,
503                   const uint32_t *p)
504 {
505    uint64_t ksp[3] = {0, 0, 0};
506    bool enabled[3] = {false, false, false};
507 
508    struct gen_field_iterator iter;
509    gen_field_iterator_init(&iter, inst, p, 0, false);
510    while (gen_field_iterator_next(&iter)) {
511       if (strncmp(iter.name, "Kernel Start Pointer ",
512                   strlen("Kernel Start Pointer ")) == 0) {
513          int idx = iter.name[strlen("Kernel Start Pointer ")] - '0';
514          ksp[idx] = strtol(iter.value, NULL, 16);
515       } else if (strcmp(iter.name, "8 Pixel Dispatch Enable") == 0) {
516          enabled[0] = strcmp(iter.value, "true") == 0;
517       } else if (strcmp(iter.name, "16 Pixel Dispatch Enable") == 0) {
518          enabled[1] = strcmp(iter.value, "true") == 0;
519       } else if (strcmp(iter.name, "32 Pixel Dispatch Enable") == 0) {
520          enabled[2] = strcmp(iter.value, "true") == 0;
521       }
522    }
523 
524    /* Reorder KSPs to be [8, 16, 32] instead of the hardware order. */
525    if (enabled[0] + enabled[1] + enabled[2] == 1) {
526       if (enabled[1]) {
527          ksp[1] = ksp[0];
528          ksp[0] = 0;
529       } else if (enabled[2]) {
530          ksp[2] = ksp[0];
531          ksp[0] = 0;
532       }
533    } else {
534       uint64_t tmp = ksp[1];
535       ksp[1] = ksp[2];
536       ksp[2] = tmp;
537    }
538 
539    if (enabled[0])
540       ctx_disassemble_program(ctx, ksp[0], "SIMD8 fragment shader");
541    if (enabled[1])
542       ctx_disassemble_program(ctx, ksp[1], "SIMD16 fragment shader");
543    if (enabled[2])
544       ctx_disassemble_program(ctx, ksp[2], "SIMD32 fragment shader");
545 }
546 
547 static void
decode_3dstate_constant(struct aub_viewer_decode_ctx * ctx,struct gen_group * inst,const uint32_t * p)548 decode_3dstate_constant(struct aub_viewer_decode_ctx *ctx,
549                         struct gen_group *inst,
550                         const uint32_t *p)
551 {
552    struct gen_group *body =
553       gen_spec_find_struct(ctx->spec, "3DSTATE_CONSTANT_BODY");
554 
555    uint32_t read_length[4] = {0};
556    uint64_t read_addr[4];
557 
558    struct gen_field_iterator outer;
559    gen_field_iterator_init(&outer, inst, p, 0, false);
560    while (gen_field_iterator_next(&outer)) {
561       if (outer.struct_desc != body)
562          continue;
563 
564       struct gen_field_iterator iter;
565       gen_field_iterator_init(&iter, body, &outer.p[outer.start_bit / 32],
566                               0, false);
567 
568       while (gen_field_iterator_next(&iter)) {
569          int idx;
570          if (sscanf(iter.name, "Read Length[%d]", &idx) == 1) {
571             read_length[idx] = iter.raw_value;
572          } else if (sscanf(iter.name, "Buffer[%d]", &idx) == 1) {
573             read_addr[idx] = iter.raw_value;
574          }
575       }
576 
577       for (int i = 0; i < 4; i++) {
578          if (read_length[i] == 0)
579             continue;
580 
581          struct gen_batch_decode_bo buffer = ctx_get_bo(ctx, true, read_addr[i]);
582          if (!buffer.map) {
583             ImGui::TextColored(ctx->cfg->missing_color,
584                                "constant buffer %d unavailable addr=0x%012" PRIx64,
585                                i, read_addr[i]);
586             continue;
587          }
588 
589          unsigned size = read_length[i] * 32;
590          ImGui::Text("constant buffer %d, size %u", i, size);
591 
592          if (ctx->edit_address) {
593             if (ImGui::Button("Show/Edit buffer"))
594                ctx->edit_address(ctx->user_data, read_addr[i], size);
595          }
596       }
597    }
598 }
599 
600 static void
decode_3dstate_binding_table_pointers(struct aub_viewer_decode_ctx * ctx,struct gen_group * inst,const uint32_t * p)601 decode_3dstate_binding_table_pointers(struct aub_viewer_decode_ctx *ctx,
602                                       struct gen_group *inst,
603                                       const uint32_t *p)
604 {
605    dump_binding_table(ctx, p[1], -1);
606 }
607 
608 static void
decode_3dstate_sampler_state_pointers(struct aub_viewer_decode_ctx * ctx,struct gen_group * inst,const uint32_t * p)609 decode_3dstate_sampler_state_pointers(struct aub_viewer_decode_ctx *ctx,
610                                       struct gen_group *inst,
611                                       const uint32_t *p)
612 {
613    dump_samplers(ctx, p[1], -1);
614 }
615 
616 static void
decode_3dstate_sampler_state_pointers_gen6(struct aub_viewer_decode_ctx * ctx,struct gen_group * inst,const uint32_t * p)617 decode_3dstate_sampler_state_pointers_gen6(struct aub_viewer_decode_ctx *ctx,
618                                            struct gen_group *inst,
619                                            const uint32_t *p)
620 {
621    dump_samplers(ctx, p[1], -1);
622    dump_samplers(ctx, p[2], -1);
623    dump_samplers(ctx, p[3], -1);
624 }
625 
626 static bool
str_ends_with(const char * str,const char * end)627 str_ends_with(const char *str, const char *end)
628 {
629    int offset = strlen(str) - strlen(end);
630    if (offset < 0)
631       return false;
632 
633    return strcmp(str + offset, end) == 0;
634 }
635 
636 static void
decode_dynamic_state_pointers(struct aub_viewer_decode_ctx * ctx,struct gen_group * inst,const uint32_t * p,const char * struct_type,int count)637 decode_dynamic_state_pointers(struct aub_viewer_decode_ctx *ctx,
638                               struct gen_group *inst, const uint32_t *p,
639                               const char *struct_type,  int count)
640 {
641    uint32_t state_offset = 0;
642 
643    struct gen_field_iterator iter;
644    gen_field_iterator_init(&iter, inst, p, 0, false);
645    while (gen_field_iterator_next(&iter)) {
646       if (str_ends_with(iter.name, "Pointer")) {
647          state_offset = iter.raw_value;
648          break;
649       }
650    }
651 
652    uint64_t state_addr = ctx->dynamic_base + state_offset;
653    struct gen_batch_decode_bo bo = ctx_get_bo(ctx, true, state_addr);
654    const uint8_t *state_map = (const uint8_t *) bo.map;
655 
656    if (state_map == NULL) {
657       ImGui::TextColored(ctx->cfg->missing_color,
658                          "dynamic %s state unavailable addr=0x%012" PRIx64,
659                          struct_type, state_addr);
660       return;
661    }
662 
663    struct gen_group *state = gen_spec_find_struct(ctx->spec, struct_type);
664    if (strcmp(struct_type, "BLEND_STATE") == 0) {
665       /* Blend states are different from the others because they have a header
666        * struct called BLEND_STATE which is followed by a variable number of
667        * BLEND_STATE_ENTRY structs.
668        */
669       ImGui::Text("%s", struct_type);
670       aub_viewer_print_group(ctx, state, state_addr, state_map);
671 
672       state_addr += state->dw_length * 4;
673       state_map += state->dw_length * 4;
674 
675       struct_type = "BLEND_STATE_ENTRY";
676       state = gen_spec_find_struct(ctx->spec, struct_type);
677    }
678 
679    for (int i = 0; i < count; i++) {
680       ImGui::Text("%s %d", struct_type, i);
681       aub_viewer_print_group(ctx, state, state_addr, state_map);
682 
683       state_addr += state->dw_length * 4;
684       state_map += state->dw_length * 4;
685    }
686 }
687 
688 static void
decode_3dstate_viewport_state_pointers_cc(struct aub_viewer_decode_ctx * ctx,struct gen_group * inst,const uint32_t * p)689 decode_3dstate_viewport_state_pointers_cc(struct aub_viewer_decode_ctx *ctx,
690                                           struct gen_group *inst,
691                                           const uint32_t *p)
692 {
693    decode_dynamic_state_pointers(ctx, inst, p, "CC_VIEWPORT", 4);
694 }
695 
696 static void
decode_3dstate_viewport_state_pointers_sf_clip(struct aub_viewer_decode_ctx * ctx,struct gen_group * inst,const uint32_t * p)697 decode_3dstate_viewport_state_pointers_sf_clip(struct aub_viewer_decode_ctx *ctx,
698                                                struct gen_group *inst,
699                                                const uint32_t *p)
700 {
701    decode_dynamic_state_pointers(ctx, inst, p, "SF_CLIP_VIEWPORT", 4);
702 }
703 
704 static void
decode_3dstate_blend_state_pointers(struct aub_viewer_decode_ctx * ctx,struct gen_group * inst,const uint32_t * p)705 decode_3dstate_blend_state_pointers(struct aub_viewer_decode_ctx *ctx,
706                                     struct gen_group *inst,
707                                     const uint32_t *p)
708 {
709    decode_dynamic_state_pointers(ctx, inst, p, "BLEND_STATE", 1);
710 }
711 
712 static void
decode_3dstate_cc_state_pointers(struct aub_viewer_decode_ctx * ctx,struct gen_group * inst,const uint32_t * p)713 decode_3dstate_cc_state_pointers(struct aub_viewer_decode_ctx *ctx,
714                                  struct gen_group *inst,
715                                  const uint32_t *p)
716 {
717    decode_dynamic_state_pointers(ctx, inst, p, "COLOR_CALC_STATE", 1);
718 }
719 
720 static void
decode_3dstate_scissor_state_pointers(struct aub_viewer_decode_ctx * ctx,struct gen_group * inst,const uint32_t * p)721 decode_3dstate_scissor_state_pointers(struct aub_viewer_decode_ctx *ctx,
722                                       struct gen_group *inst,
723                                       const uint32_t *p)
724 {
725    decode_dynamic_state_pointers(ctx, inst, p, "SCISSOR_RECT", 1);
726 }
727 
728 static void
decode_load_register_imm(struct aub_viewer_decode_ctx * ctx,struct gen_group * inst,const uint32_t * p)729 decode_load_register_imm(struct aub_viewer_decode_ctx *ctx,
730                          struct gen_group *inst,
731                          const uint32_t *p)
732 {
733    struct gen_group *reg = gen_spec_find_register(ctx->spec, p[1]);
734 
735    if (reg != NULL &&
736        ImGui::TreeNodeEx(&p[1], ImGuiTreeNodeFlags_Framed,
737                          "%s (0x%x) = 0x%x",
738                          reg->name, reg->register_offset, p[2])) {
739       aub_viewer_print_group(ctx, reg, reg->register_offset, &p[2]);
740       ImGui::TreePop();
741    }
742 }
743 
744 static void
decode_3dprimitive(struct aub_viewer_decode_ctx * ctx,struct gen_group * inst,const uint32_t * p)745 decode_3dprimitive(struct aub_viewer_decode_ctx *ctx,
746                    struct gen_group *inst,
747                    const uint32_t *p)
748 {
749    if (ctx->display_urb) {
750       if (ImGui::Button("Show URB"))
751          ctx->display_urb(ctx->user_data, ctx->urb_stages);
752    }
753 }
754 
755 static void
handle_urb(struct aub_viewer_decode_ctx * ctx,struct gen_group * inst,const uint32_t * p)756 handle_urb(struct aub_viewer_decode_ctx *ctx,
757            struct gen_group *inst,
758            const uint32_t *p)
759 {
760    struct gen_field_iterator iter;
761    gen_field_iterator_init(&iter, inst, p, 0, false);
762    while (gen_field_iterator_next(&iter)) {
763       if (strstr(iter.name, "URB Starting Address")) {
764          ctx->urb_stages[ctx->stage].start = iter.raw_value * 8192;
765       } else if (strstr(iter.name, "URB Entry Allocation Size")) {
766          ctx->urb_stages[ctx->stage].size = (iter.raw_value + 1) * 64;
767       } else if (strstr(iter.name, "Number of URB Entries")) {
768          ctx->urb_stages[ctx->stage].n_entries = iter.raw_value;
769       }
770    }
771 
772    ctx->end_urb_offset = MAX2(ctx->urb_stages[ctx->stage].start +
773                               ctx->urb_stages[ctx->stage].n_entries *
774                               ctx->urb_stages[ctx->stage].size,
775                               ctx->end_urb_offset);
776 }
777 
778 static void
handle_urb_read(struct aub_viewer_decode_ctx * ctx,struct gen_group * inst,const uint32_t * p)779 handle_urb_read(struct aub_viewer_decode_ctx *ctx,
780                 struct gen_group *inst,
781                 const uint32_t *p)
782 {
783    struct gen_field_iterator iter;
784    gen_field_iterator_init(&iter, inst, p, 0, false);
785    while (gen_field_iterator_next(&iter)) {
786       /* Workaround the "Force * URB Entry Read Length" fields */
787       if (iter.end_bit - iter.start_bit < 2)
788          continue;
789 
790       if (strstr(iter.name, "URB Entry Read Offset")) {
791          ctx->urb_stages[ctx->stage].rd_offset = iter.raw_value * 32;
792       } else if (strstr(iter.name, "URB Entry Read Length")) {
793          ctx->urb_stages[ctx->stage].rd_length = iter.raw_value * 32;
794       } else if (strstr(iter.name, "URB Entry Output Read Offset")) {
795          ctx->urb_stages[ctx->stage].wr_offset = iter.raw_value * 32;
796       } else if (strstr(iter.name, "URB Entry Output Length")) {
797          ctx->urb_stages[ctx->stage].wr_length = iter.raw_value * 32;
798       }
799    }
800 }
801 
802 static void
handle_urb_constant(struct aub_viewer_decode_ctx * ctx,struct gen_group * inst,const uint32_t * p)803 handle_urb_constant(struct aub_viewer_decode_ctx *ctx,
804                     struct gen_group *inst,
805                     const uint32_t *p)
806 {
807    struct gen_group *body =
808       gen_spec_find_struct(ctx->spec, "3DSTATE_CONSTANT_BODY");
809 
810    struct gen_field_iterator outer;
811    gen_field_iterator_init(&outer, inst, p, 0, false);
812    while (gen_field_iterator_next(&outer)) {
813       if (outer.struct_desc != body)
814          continue;
815 
816       struct gen_field_iterator iter;
817       gen_field_iterator_init(&iter, body, &outer.p[outer.start_bit / 32],
818                               0, false);
819 
820       ctx->urb_stages[ctx->stage].const_rd_length = 0;
821       while (gen_field_iterator_next(&iter)) {
822          int idx;
823          if (sscanf(iter.name, "Read Length[%d]", &idx) == 1) {
824             ctx->urb_stages[ctx->stage].const_rd_length += iter.raw_value * 32;
825          }
826       }
827    }
828 }
829 
830 struct custom_decoder {
831    const char *cmd_name;
832    void (*decode)(struct aub_viewer_decode_ctx *ctx,
833                   struct gen_group *inst,
834                   const uint32_t *p);
835    enum aub_decode_stage stage;
836 } display_decoders[] = {
837    { "STATE_BASE_ADDRESS", handle_state_base_address },
838    { "MEDIA_INTERFACE_DESCRIPTOR_LOAD", handle_media_interface_descriptor_load },
839    { "3DSTATE_VERTEX_BUFFERS", handle_3dstate_vertex_buffers },
840    { "3DSTATE_INDEX_BUFFER", handle_3dstate_index_buffer },
841    { "3DSTATE_VS", decode_single_ksp, AUB_DECODE_STAGE_VS, },
842    { "3DSTATE_GS", decode_single_ksp, AUB_DECODE_STAGE_GS, },
843    { "3DSTATE_DS", decode_single_ksp, AUB_DECODE_STAGE_DS, },
844    { "3DSTATE_HS", decode_single_ksp, AUB_DECODE_STAGE_HS, },
845    { "3DSTATE_PS", decode_ps_kernels, AUB_DECODE_STAGE_PS, },
846    { "3DSTATE_CONSTANT_VS", decode_3dstate_constant, AUB_DECODE_STAGE_VS, },
847    { "3DSTATE_CONSTANT_GS", decode_3dstate_constant, AUB_DECODE_STAGE_GS, },
848    { "3DSTATE_CONSTANT_DS", decode_3dstate_constant, AUB_DECODE_STAGE_DS, },
849    { "3DSTATE_CONSTANT_HS", decode_3dstate_constant, AUB_DECODE_STAGE_HS, },
850    { "3DSTATE_CONSTANT_PS", decode_3dstate_constant, AUB_DECODE_STAGE_PS, },
851 
852    { "3DSTATE_BINDING_TABLE_POINTERS_VS", decode_3dstate_binding_table_pointers, AUB_DECODE_STAGE_VS, },
853    { "3DSTATE_BINDING_TABLE_POINTERS_GS", decode_3dstate_binding_table_pointers, AUB_DECODE_STAGE_GS, },
854    { "3DSTATE_BINDING_TABLE_POINTERS_HS", decode_3dstate_binding_table_pointers, AUB_DECODE_STAGE_HS, },
855    { "3DSTATE_BINDING_TABLE_POINTERS_DS", decode_3dstate_binding_table_pointers, AUB_DECODE_STAGE_DS, },
856    { "3DSTATE_BINDING_TABLE_POINTERS_PS", decode_3dstate_binding_table_pointers, AUB_DECODE_STAGE_PS, },
857 
858    { "3DSTATE_SAMPLER_STATE_POINTERS_VS", decode_3dstate_sampler_state_pointers, AUB_DECODE_STAGE_VS, },
859    { "3DSTATE_SAMPLER_STATE_POINTERS_GS", decode_3dstate_sampler_state_pointers, AUB_DECODE_STAGE_GS, },
860    { "3DSTATE_SAMPLER_STATE_POINTERS_DS", decode_3dstate_sampler_state_pointers, AUB_DECODE_STAGE_DS, },
861    { "3DSTATE_SAMPLER_STATE_POINTERS_HS", decode_3dstate_sampler_state_pointers, AUB_DECODE_STAGE_HS, },
862    { "3DSTATE_SAMPLER_STATE_POINTERS_PS", decode_3dstate_sampler_state_pointers, AUB_DECODE_STAGE_PS, },
863    { "3DSTATE_SAMPLER_STATE_POINTERS", decode_3dstate_sampler_state_pointers_gen6 },
864 
865    { "3DSTATE_VIEWPORT_STATE_POINTERS_CC", decode_3dstate_viewport_state_pointers_cc },
866    { "3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP", decode_3dstate_viewport_state_pointers_sf_clip },
867    { "3DSTATE_BLEND_STATE_POINTERS", decode_3dstate_blend_state_pointers },
868    { "3DSTATE_CC_STATE_POINTERS", decode_3dstate_cc_state_pointers },
869    { "3DSTATE_SCISSOR_STATE_POINTERS", decode_3dstate_scissor_state_pointers },
870    { "MI_LOAD_REGISTER_IMM", decode_load_register_imm },
871    { "3DPRIMITIVE", decode_3dprimitive },
872 };
873 
874 struct custom_decoder info_decoders[] = {
875    { "STATE_BASE_ADDRESS", handle_state_base_address },
876    { "3DSTATE_URB_VS", handle_urb, AUB_DECODE_STAGE_VS, },
877    { "3DSTATE_URB_GS", handle_urb, AUB_DECODE_STAGE_GS, },
878    { "3DSTATE_URB_DS", handle_urb, AUB_DECODE_STAGE_DS, },
879    { "3DSTATE_URB_HS", handle_urb, AUB_DECODE_STAGE_HS, },
880    { "3DSTATE_VS", handle_urb_read, AUB_DECODE_STAGE_VS, },
881    { "3DSTATE_GS", handle_urb_read, AUB_DECODE_STAGE_GS, },
882    { "3DSTATE_DS", handle_urb_read, AUB_DECODE_STAGE_DS, },
883    { "3DSTATE_HS", handle_urb_read, AUB_DECODE_STAGE_HS, },
884    { "3DSTATE_PS", handle_urb_read, AUB_DECODE_STAGE_PS, },
885    { "3DSTATE_CONSTANT_VS", handle_urb_constant, AUB_DECODE_STAGE_VS, },
886    { "3DSTATE_CONSTANT_GS", handle_urb_constant, AUB_DECODE_STAGE_GS, },
887    { "3DSTATE_CONSTANT_DS", handle_urb_constant, AUB_DECODE_STAGE_DS, },
888    { "3DSTATE_CONSTANT_HS", handle_urb_constant, AUB_DECODE_STAGE_HS, },
889    { "3DSTATE_CONSTANT_PS", handle_urb_constant, AUB_DECODE_STAGE_PS, },
890 };
891 
892 void
aub_viewer_render_batch(struct aub_viewer_decode_ctx * ctx,const void * _batch,uint32_t batch_size,uint64_t batch_addr,bool from_ring)893 aub_viewer_render_batch(struct aub_viewer_decode_ctx *ctx,
894                         const void *_batch, uint32_t batch_size,
895                         uint64_t batch_addr, bool from_ring)
896 {
897    struct gen_group *inst;
898    const uint32_t *p, *batch = (const uint32_t *) _batch, *end = batch + batch_size / sizeof(uint32_t);
899    int length;
900 
901    if (ctx->n_batch_buffer_start >= 100) {
902       ImGui::TextColored(ctx->cfg->error_color,
903                          "0x%08" PRIx64 ": Max batch buffer jumps exceeded", batch_addr);
904       return;
905    }
906 
907    ctx->n_batch_buffer_start++;
908 
909    for (p = batch; p < end; p += length) {
910       inst = gen_spec_find_instruction(ctx->spec, ctx->engine, p);
911       length = gen_group_get_length(inst, p);
912       assert(inst == NULL || length > 0);
913       length = MAX2(1, length);
914 
915       uint64_t offset = batch_addr + ((char *)p - (char *)batch);
916 
917       if (inst == NULL) {
918          ImGui::TextColored(ctx->cfg->error_color,
919                             "0x%012" PRIx64 ": unknown instruction %012x",
920                             offset, p[0]);
921          continue;
922       }
923 
924       const char *inst_name = gen_group_get_name(inst);
925 
926       for (unsigned i = 0; i < ARRAY_SIZE(info_decoders); i++) {
927          if (strcmp(inst_name, info_decoders[i].cmd_name) == 0) {
928             ctx->stage = info_decoders[i].stage;
929             info_decoders[i].decode(ctx, inst, p);
930             break;
931          }
932       }
933 
934       if (ctx->decode_cfg->command_filter.PassFilter(inst->name) &&
935           ImGui::TreeNodeEx(p,
936                             ImGuiTreeNodeFlags_Framed,
937                             "0x%012" PRIx64 ":  %s",
938                             offset, inst->name)) {
939          aub_viewer_print_group(ctx, inst, offset, p);
940 
941          for (unsigned i = 0; i < ARRAY_SIZE(display_decoders); i++) {
942             if (strcmp(inst_name, display_decoders[i].cmd_name) == 0) {
943                ctx->stage = display_decoders[i].stage;
944                display_decoders[i].decode(ctx, inst, p);
945                break;
946             }
947          }
948 
949          if (ctx->edit_address) {
950             if (ImGui::Button("Edit instruction"))
951                ctx->edit_address(ctx->user_data, offset, length * 4);
952          }
953 
954          ImGui::TreePop();
955       }
956 
957       if (strcmp(inst_name, "MI_BATCH_BUFFER_START") == 0) {
958          uint64_t next_batch_addr = 0xd0d0d0d0;
959          bool ppgtt = false;
960          bool second_level = false;
961          struct gen_field_iterator iter;
962          gen_field_iterator_init(&iter, inst, p, 0, false);
963          while (gen_field_iterator_next(&iter)) {
964             if (strcmp(iter.name, "Batch Buffer Start Address") == 0) {
965                next_batch_addr = iter.raw_value;
966             } else if (strcmp(iter.name, "Second Level Batch Buffer") == 0) {
967                second_level = iter.raw_value;
968             } else if (strcmp(iter.name, "Address Space Indicator") == 0) {
969                ppgtt = iter.raw_value;
970             }
971          }
972 
973          struct gen_batch_decode_bo next_batch = ctx_get_bo(ctx, ppgtt, next_batch_addr);
974 
975          if (next_batch.map == NULL) {
976             ImGui::TextColored(ctx->cfg->missing_color,
977                                "Secondary batch at 0x%012" PRIx64 " unavailable",
978                                next_batch_addr);
979          } else {
980             aub_viewer_render_batch(ctx, next_batch.map, next_batch.size,
981                                     next_batch.addr, false);
982          }
983          if (second_level) {
984             /* MI_BATCH_BUFFER_START with "2nd Level Batch Buffer" set acts
985              * like a subroutine call.  Commands that come afterwards get
986              * processed once the 2nd level batch buffer returns with
987              * MI_BATCH_BUFFER_END.
988              */
989             continue;
990          } else if (!from_ring) {
991             /* MI_BATCH_BUFFER_START with "2nd Level Batch Buffer" unset acts
992              * like a goto.  Nothing after it will ever get processed.  In
993              * order to prevent the recursion from growing, we just reset the
994              * loop and continue;
995              */
996             break;
997          }
998       } else if (strcmp(inst_name, "MI_BATCH_BUFFER_END") == 0) {
999          break;
1000       }
1001    }
1002 
1003    ctx->n_batch_buffer_start--;
1004 }
1005