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
30void
31aub_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
53static void
54aub_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
94static struct intel_batch_decode_bo
95ctx_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
124static int
125update_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
142static void
143ctx_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
160static void
161handle_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
197static void
198dump_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
250static void
251dump_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
288static void
289handle_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
352static void
353handle_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
417static void
418handle_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
464static void
465decode_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
504static void
505decode_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
551static void
552decode_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
604static void
605decode_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
612static void
613decode_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
620static void
621decode_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
630static bool
631str_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
640static void
641decode_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
692static void
693decode_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
700static void
701decode_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
708static void
709decode_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
716static void
717decode_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
724static void
725decode_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
732static void
733decode_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
748static void
749decode_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
759static void
760handle_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
782static void
783handle_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
806static void
807handle_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
834struct 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
878struct 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
896void
897aub_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