struct aub_viewer_decode_cfg *decode_cfg,
struct gen_spec *spec,
struct gen_disasm *disasm,
- struct gen_batch_decode_bo (*get_bo)(void *, uint64_t),
+ struct gen_batch_decode_bo (*get_bo)(void *, bool, uint64_t),
unsigned (*get_state_size)(void *, uint32_t),
void *user_data)
{
ctx->get_bo = get_bo;
ctx->get_state_size = get_state_size;
ctx->user_data = user_data;
+ ctx->engine = I915_ENGINE_CLASS_RENDER;
ctx->cfg = cfg;
ctx->decode_cfg = decode_cfg;
if (last_dword != iter_dword) {
for (int i = last_dword + 1; i <= iter_dword; i++) {
ImGui::TextColored(ctx->cfg->dwords_color,
- "0x%08" PRIx64 ": 0x%08x : Dword %d",
+ "0x%012" PRIx64 ": 0x%012x : Dword %d",
address + 4 * i, iter.p[i], i);
}
last_dword = iter_dword;
}
if (!gen_field_is_header(iter.field)) {
if (ctx->decode_cfg->field_filter.PassFilter(iter.name)) {
- ImGui::Text("%s: %s", iter.name, iter.value);
+ if (iter.field->type.kind == gen_type::GEN_TYPE_BOOL && iter.raw_value) {
+ ImGui::Text("%s: ", iter.name); ImGui::SameLine();
+ ImGui::TextColored(ctx->cfg->boolean_color, "true");
+ } else {
+ ImGui::Text("%s: %s", iter.name, iter.value);
+ }
if (iter.struct_desc) {
int struct_dword = iter.start_bit / 32;
uint64_t struct_address = address + 4 * struct_dword;
}
static struct gen_batch_decode_bo
-ctx_get_bo(struct aub_viewer_decode_ctx *ctx, uint64_t addr)
+ctx_get_bo(struct aub_viewer_decode_ctx *ctx, bool ppgtt, uint64_t addr)
{
if (gen_spec_get_gen(ctx->spec) >= gen_make_gen(8,0)) {
/* On Broadwell and above, we have 48-bit addresses which consume two
addr &= (~0ull >> 16);
}
- struct gen_batch_decode_bo bo = ctx->get_bo(ctx->user_data, addr);
+ struct gen_batch_decode_bo bo = ctx->get_bo(ctx->user_data, ppgtt, addr);
if (gen_spec_get_gen(ctx->spec) >= gen_make_gen(8,0))
bo.addr &= (~0ull >> 16);
uint32_t ksp, const char *type)
{
uint64_t addr = ctx->instruction_base + ksp;
- struct gen_batch_decode_bo bo = ctx_get_bo(ctx, addr);
+ struct gen_batch_decode_bo bo = ctx_get_bo(ctx, true, addr);
if (!bo.map) {
- ImGui::TextColored(ctx->cfg->missing_color, "Shader unavailable");
+ ImGui::TextColored(ctx->cfg->missing_color,
+ "Shader unavailable addr=0x%012" PRIx64, addr);
return;
}
surface_modify = iter.raw_value;
} else if (strcmp(iter.name, "Dynamic State Base Address Modify Enable") == 0) {
dynamic_modify = iter.raw_value;
- } else if (strcmp(iter.name, "Insntruction Base Address Modify Enable") == 0) {
+ } else if (strcmp(iter.name, "Instruction Base Address Modify Enable") == 0) {
instruction_modify = iter.raw_value;
}
}
}
struct gen_batch_decode_bo bind_bo =
- ctx_get_bo(ctx, ctx->surface_base + offset);
+ ctx_get_bo(ctx, true, ctx->surface_base + offset);
if (bind_bo.map == NULL) {
ImGui::TextColored(ctx->cfg->missing_color,
- "binding table unavailable addr=0x%08" PRIx64,
+ "binding table unavailable addr=0x%012" PRIx64,
ctx->surface_base + offset);
return;
}
continue;
uint64_t addr = ctx->surface_base + pointers[i];
- struct gen_batch_decode_bo bo = ctx_get_bo(ctx, addr);
+ struct gen_batch_decode_bo bo = ctx_get_bo(ctx, true, addr);
uint32_t size = strct->dw_length * 4;
if (pointers[i] % 32 != 0 ||
addr < bo.addr || addr + size >= bo.addr + bo.size) {
ImGui::TextColored(ctx->cfg->missing_color,
- "pointer %u: %08x <not valid>", i, pointers[i]);
+ "pointer %u: %012x <not valid>", i, pointers[i]);
continue;
}
- ImGui::Text("pointer %u: %08x", i, pointers[i]);
- aub_viewer_print_group(ctx, strct, addr, (const uint8_t *) bo.map + (addr - bo.addr));
+ const uint8_t *state = (const uint8_t *) bo.map + (addr - bo.addr);
+ if (ImGui::TreeNodeEx(&pointers[i], ImGuiTreeNodeFlags_Framed,
+ "pointer %u: %012x", i, pointers[i])) {
+ aub_viewer_print_group(ctx, strct, addr, state);
+ ImGui::TreePop();
+ }
}
}
count = update_count(ctx, offset, strct->dw_length, 4);
uint64_t state_addr = ctx->dynamic_base + offset;
- struct gen_batch_decode_bo bo = ctx_get_bo(ctx, state_addr);
+ struct gen_batch_decode_bo bo = ctx_get_bo(ctx, true, state_addr);
const uint8_t *state_map = (const uint8_t *) bo.map;
if (state_map == NULL) {
ImGui::TextColored(ctx->cfg->missing_color,
- "samplers unavailable addr=0x%08" PRIx64, state_addr);
+ "samplers unavailable addr=0x%012" PRIx64, state_addr);
return;
}
}
for (int i = 0; i < count; i++) {
- ImGui::Text("sampler state %d", i);
- aub_viewer_print_group(ctx, strct, state_addr, state_map);
+ if (ImGui::TreeNodeEx(state_map, ImGuiTreeNodeFlags_Framed,
+ "sampler state %d", i)) {
+ aub_viewer_print_group(ctx, strct, state_addr, state_map);
+ ImGui::TreePop();
+ }
state_addr += 16;
state_map += 16;
}
}
uint64_t desc_addr = ctx->dynamic_base + descriptor_offset;
- struct gen_batch_decode_bo bo = ctx_get_bo(ctx, desc_addr);
+ struct gen_batch_decode_bo bo = ctx_get_bo(ctx, true, desc_addr);
const uint32_t *desc_map = (const uint32_t *) bo.map;
if (desc_map == NULL) {
ImGui::TextColored(ctx->cfg->missing_color,
- "interface descriptors unavailable addr=0x%08" PRIx64, desc_addr);
+ "interface descriptors unavailable addr=0x%012" PRIx64, desc_addr);
return;
}
for (int i = 0; i < descriptor_count; i++) {
- ImGui::Text("descriptor %d: %08x", i, descriptor_offset);
+ ImGui::Text("descriptor %d: %012x", i, descriptor_offset);
aub_viewer_print_group(ctx, desc, desc_addr, desc_map);
if (iter.struct_desc != vbs)
continue;
- uint64_t buffer_addr;
+ uint64_t buffer_addr = 0;
struct gen_field_iterator vbs_iter;
gen_field_iterator_init(&vbs_iter, vbs, &iter.p[iter.start_bit / 32], 0, false);
pitch = vbs_iter.raw_value;
} else if (strcmp(vbs_iter.name, "Buffer Starting Address") == 0) {
buffer_addr = vbs_iter.raw_value;
- vb = ctx_get_bo(ctx, buffer_addr);
+ vb = ctx_get_bo(ctx, true, buffer_addr);
} else if (strcmp(vbs_iter.name, "Buffer Size") == 0) {
vb_size = vbs_iter.raw_value;
ready = true;
if (!ready)
continue;
- ImGui::Text("vertex buffer %d, size %d", index, vb_size);
+ ImGui::Text("vertex buffer %d, size %d, pitch %d", index, vb_size, pitch);
if (vb.map == NULL) {
ImGui::TextColored(ctx->cfg->missing_color,
- "buffer contents unavailable addr=0x%08" PRIx64, buffer_addr);
+ "buffer contents unavailable addr=0x%012" PRIx64, buffer_addr);
continue;
}
format = iter.raw_value;
} else if (strcmp(iter.name, "Buffer Starting Address") == 0) {
buffer_addr = iter.raw_value;
- ib = ctx_get_bo(ctx, buffer_addr);
+ ib = ctx_get_bo(ctx, true, buffer_addr);
} else if (strcmp(iter.name, "Buffer Size") == 0) {
ib_size = iter.raw_value;
}
if (ib.map == NULL) {
ImGui::TextColored(ctx->cfg->missing_color,
- "buffer contents unavailable addr=0x%08" PRIx64,
+ "buffer contents unavailable addr=0x%012" PRIx64,
buffer_addr);
return;
}
if (read_length[i] == 0)
continue;
- struct gen_batch_decode_bo buffer = ctx_get_bo(ctx, read_addr[i]);
+ struct gen_batch_decode_bo buffer = ctx_get_bo(ctx, true, read_addr[i]);
if (!buffer.map) {
ImGui::TextColored(ctx->cfg->missing_color,
- "constant buffer %d unavailable addr=0x%08" PRIx64,
+ "constant buffer %d unavailable addr=0x%012" PRIx64,
i, read_addr[i]);
continue;
}
struct gen_group *inst, const uint32_t *p,
const char *struct_type, int count)
{
- struct gen_group *state = gen_spec_find_struct(ctx->spec, struct_type);
-
uint32_t state_offset = 0;
struct gen_field_iterator iter;
}
uint64_t state_addr = ctx->dynamic_base + state_offset;
- struct gen_batch_decode_bo bo = ctx_get_bo(ctx, state_addr);
+ struct gen_batch_decode_bo bo = ctx_get_bo(ctx, true, state_addr);
const uint8_t *state_map = (const uint8_t *) bo.map;
if (state_map == NULL) {
ImGui::TextColored(ctx->cfg->missing_color,
- "dynamic %s state unavailable addr=0x%08" PRIx64,
+ "dynamic %s state unavailable addr=0x%012" PRIx64,
struct_type, state_addr);
return;
}
+ struct gen_group *state = gen_spec_find_struct(ctx->spec, struct_type);
+ if (strcmp(struct_type, "BLEND_STATE") == 0) {
+ /* Blend states are different from the others because they have a header
+ * struct called BLEND_STATE which is followed by a variable number of
+ * BLEND_STATE_ENTRY structs.
+ */
+ ImGui::Text("%s", struct_type);
+ aub_viewer_print_group(ctx, state, state_addr, state_map);
+
+ state_addr += state->dw_length * 4;
+ state_map += state->dw_length * 4;
+
+ struct_type = "BLEND_STATE_ENTRY";
+ state = gen_spec_find_struct(ctx->spec, struct_type);
+ }
+
for (int i = 0; i < count; i++) {
ImGui::Text("%s %d", struct_type, i);
- aub_viewer_print_group(ctx, state, state_offset, state_map);
+ aub_viewer_print_group(ctx, state, state_addr, state_map);
state_addr += state->dw_length * 4;
- state_map += state->dw_length;
+ state_map += state->dw_length * 4;
}
}
void
aub_viewer_render_batch(struct aub_viewer_decode_ctx *ctx,
const void *_batch, uint32_t batch_size,
- uint64_t batch_addr)
+ uint64_t batch_addr, bool from_ring)
{
struct gen_group *inst;
const uint32_t *p, *batch = (const uint32_t *) _batch, *end = batch + batch_size / sizeof(uint32_t);
int length;
+ if (ctx->n_batch_buffer_start >= 100) {
+ ImGui::TextColored(ctx->cfg->error_color,
+ "0x%08" PRIx64 ": Max batch buffer jumps exceeded", batch_addr);
+ return;
+ }
+
+ ctx->n_batch_buffer_start++;
+
for (p = batch; p < end; p += length) {
- inst = gen_spec_find_instruction(ctx->spec, p);
+ inst = gen_spec_find_instruction(ctx->spec, ctx->engine, p);
length = gen_group_get_length(inst, p);
assert(inst == NULL || length > 0);
length = MAX2(1, length);
if (inst == NULL) {
ImGui::TextColored(ctx->cfg->error_color,
- "x%08" PRIx64 ": unknown instruction %08x",
+ "0x%012" PRIx64 ": unknown instruction %012x",
offset, p[0]);
continue;
}
if (ctx->decode_cfg->command_filter.PassFilter(inst->name) &&
ImGui::TreeNodeEx(p,
ImGuiTreeNodeFlags_Framed,
- "0x%08" PRIx64 ": %s",
+ "0x%012" PRIx64 ": %s",
offset, inst->name)) {
aub_viewer_print_group(ctx, inst, offset, p);
}
if (strcmp(inst_name, "MI_BATCH_BUFFER_START") == 0) {
- struct gen_batch_decode_bo next_batch = {};
- bool second_level;
+ uint64_t next_batch_addr = 0xd0d0d0d0;
+ bool ppgtt = false;
+ bool second_level = false;
struct gen_field_iterator iter;
gen_field_iterator_init(&iter, inst, p, 0, false);
while (gen_field_iterator_next(&iter)) {
if (strcmp(iter.name, "Batch Buffer Start Address") == 0) {
- next_batch = ctx_get_bo(ctx, iter.raw_value);
+ next_batch_addr = iter.raw_value;
} else if (strcmp(iter.name, "Second Level Batch Buffer") == 0) {
second_level = iter.raw_value;
+ } else if (strcmp(iter.name, "Address Space Indicator") == 0) {
+ ppgtt = iter.raw_value;
}
}
+ struct gen_batch_decode_bo next_batch = ctx_get_bo(ctx, ppgtt, next_batch_addr);
+
if (next_batch.map == NULL) {
ImGui::TextColored(ctx->cfg->missing_color,
- "Secondary batch at 0x%08" PRIx64 " unavailable",
- next_batch.addr);
+ "Secondary batch at 0x%012" PRIx64 " unavailable",
+ next_batch_addr);
} else {
aub_viewer_render_batch(ctx, next_batch.map, next_batch.size,
- next_batch.addr);
+ next_batch.addr, false);
}
if (second_level) {
/* MI_BATCH_BUFFER_START with "2nd Level Batch Buffer" set acts
* MI_BATCH_BUFFER_END.
*/
continue;
- } else {
+ } else if (!from_ring) {
/* MI_BATCH_BUFFER_START with "2nd Level Batch Buffer" unset acts
* like a goto. Nothing after it will ever get processed. In
* order to prevent the recursion from growing, we just reset the
break;
}
}
+
+ ctx->n_batch_buffer_start--;
}