• 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 intel_device_info * devinfo,struct intel_spec * spec,struct intel_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 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
aub_viewer_print_group(struct aub_viewer_decode_ctx * ctx,struct intel_group * group,uint64_t address,const void * map)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
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 (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
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 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
handle_state_base_address(struct aub_viewer_decode_ctx * ctx,struct intel_group * inst,const uint32_t * p)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
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 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
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 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
handle_media_interface_descriptor_load(struct aub_viewer_decode_ctx * ctx,struct intel_group * inst,const uint32_t * p)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
handle_3dstate_vertex_buffers(struct aub_viewer_decode_ctx * ctx,struct intel_group * inst,const uint32_t * p)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
handle_3dstate_index_buffer(struct aub_viewer_decode_ctx * ctx,struct intel_group * inst,const uint32_t * p)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
decode_single_ksp(struct aub_viewer_decode_ctx * ctx,struct intel_group * inst,const uint32_t * p)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
decode_ps_kernels(struct aub_viewer_decode_ctx * ctx,struct intel_group * inst,const uint32_t * p)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
decode_3dstate_constant(struct aub_viewer_decode_ctx * ctx,struct intel_group * inst,const uint32_t * p)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
decode_3dstate_binding_table_pointers(struct aub_viewer_decode_ctx * ctx,struct intel_group * inst,const uint32_t * p)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
decode_3dstate_sampler_state_pointers(struct aub_viewer_decode_ctx * ctx,struct intel_group * inst,const uint32_t * p)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
decode_3dstate_sampler_state_pointers_gfx6(struct aub_viewer_decode_ctx * ctx,struct intel_group * inst,const uint32_t * p)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
str_ends_with(const char * str,const char * end)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
decode_dynamic_state_pointers(struct aub_viewer_decode_ctx * ctx,struct intel_group * inst,const uint32_t * p,const char * struct_type,int count)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
decode_3dstate_viewport_state_pointers_cc(struct aub_viewer_decode_ctx * ctx,struct intel_group * inst,const uint32_t * p)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
decode_3dstate_viewport_state_pointers_sf_clip(struct aub_viewer_decode_ctx * ctx,struct intel_group * inst,const uint32_t * p)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
decode_3dstate_blend_state_pointers(struct aub_viewer_decode_ctx * ctx,struct intel_group * inst,const uint32_t * p)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
decode_3dstate_cc_state_pointers(struct aub_viewer_decode_ctx * ctx,struct intel_group * inst,const uint32_t * p)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
decode_3dstate_scissor_state_pointers(struct aub_viewer_decode_ctx * ctx,struct intel_group * inst,const uint32_t * p)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
decode_load_register_imm(struct aub_viewer_decode_ctx * ctx,struct intel_group * inst,const uint32_t * p)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
decode_3dprimitive(struct aub_viewer_decode_ctx * ctx,struct intel_group * inst,const uint32_t * p)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
handle_urb(struct aub_viewer_decode_ctx * ctx,struct intel_group * inst,const uint32_t * p)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
handle_urb_read(struct aub_viewer_decode_ctx * ctx,struct intel_group * inst,const uint32_t * p)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
handle_urb_constant(struct aub_viewer_decode_ctx * ctx,struct intel_group * inst,const uint32_t * p)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
aub_viewer_render_batch(struct aub_viewer_decode_ctx * ctx,const void * _batch,uint32_t batch_size,uint64_t batch_addr,bool from_ring)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