From 933223db3ceacad9f25a6c74213a54854550315b Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Wed, 11 Jul 2018 10:50:16 -0700 Subject: [PATCH] intel: Make the decoder handle STATE_BASE_ADDRESS not being a buffer. Normally, i965 programs STATE_BASE_ADDRESS every batch, and puts all state for a given base in a single buffer. I'm working on a prototype which emits STATE_BASE_ADDRESS only once at startup, where each base address is a fixed 4GB region of the PPGTT. State may live in many buffers in that 4GB region, even if there isn't a buffer located at the actual base address itself. To handle this, we need to save the STATE_BASE_ADDRESS values across multiple batches, rather than assuming we'll see the command each time. Then, each time we see a pointer, we need to ask the driver for the BO map for that data. (We can't just use the map for the base address, as state may be in multiple buffers, and there may not even be a buffer at the base address to map.) v2: Fix things caught in review by Lionel: - Drop bogus bind_bo.size check. - Drop "get the BOs again" code - we just get the BOs as needed - Add a message about interface descriptor data being unavailable Reviewed-by: Lionel Landwerlin --- src/intel/common/gen_batch_decoder.c | 75 +++++++++++++++------------- src/intel/common/gen_decoder.h | 9 +++- 2 files changed, 46 insertions(+), 38 deletions(-) diff --git a/src/intel/common/gen_batch_decoder.c b/src/intel/common/gen_batch_decoder.c index 727cbb80cfb..c6967ebc053 100644 --- a/src/intel/common/gen_batch_decoder.c +++ b/src/intel/common/gen_batch_decoder.c @@ -128,13 +128,13 @@ static void ctx_disassemble_program(struct gen_batch_decode_ctx *ctx, uint32_t ksp, const char *type) { - if (!ctx->instruction_base.map) + uint64_t addr = ctx->instruction_base.addr + ksp; + struct gen_batch_decode_bo bo = ctx_get_bo(ctx, addr); + if (!bo.map) return; - printf("\nReferenced %s:\n", type); - gen_disasm_disassemble(ctx->disasm, - (void *)ctx->instruction_base.map, ksp, - ctx->fp); + fprintf(ctx->fp, "\nReferenced %s:\n", type); + gen_disasm_disassemble(ctx->disasm, bo.map, 0, ctx->fp); } /* Heuristic to determine whether a uint32_t is probably actually a float @@ -225,35 +225,30 @@ dump_binding_table(struct gen_batch_decode_ctx *ctx, uint32_t offset, int count) if (count < 0) count = update_count(ctx, offset, 1, 8); - if (ctx->surface_base.map == NULL) { - fprintf(ctx->fp, " binding table unavailable\n"); + if (offset % 32 != 0 || offset >= UINT16_MAX) { + fprintf(ctx->fp, " invalid binding table pointer\n"); return; } - if (offset % 32 != 0 || offset >= UINT16_MAX || - offset >= ctx->surface_base.size) { - fprintf(ctx->fp, " invalid binding table pointer\n"); + struct gen_batch_decode_bo bind_bo = + ctx_get_bo(ctx, ctx->surface_base.addr + offset); + + if (bind_bo.map == NULL) { + fprintf(ctx->fp, " binding table unavailable\n"); return; } - struct gen_batch_decode_bo bo = ctx->surface_base; - const uint32_t *pointers = ctx->surface_base.map + offset; + const uint32_t *pointers = bind_bo.map; for (int i = 0; i < count; i++) { if (pointers[i] == 0) continue; - if (pointers[i] % 32 != 0) { - fprintf(ctx->fp, "pointer %u: %08x \n", i, pointers[i]); - continue; - } - uint64_t addr = ctx->surface_base.addr + pointers[i]; + struct gen_batch_decode_bo bo = ctx_get_bo(ctx, addr); uint32_t size = strct->dw_length * 4; - if (addr < bo.addr || addr + size >= bo.addr + bo.size) - bo = ctx->get_bo(ctx->user_data, addr); - - if (addr < bo.addr || addr + size >= bo.addr + bo.size) { + if (pointers[i] % 32 != 0 || + addr < bo.addr || addr + size >= bo.addr + bo.size) { fprintf(ctx->fp, "pointer %u: %08x \n", i, pointers[i]); continue; } @@ -271,18 +266,20 @@ dump_samplers(struct gen_batch_decode_ctx *ctx, uint32_t offset, int count) if (count < 0) count = update_count(ctx, offset, strct->dw_length, 4); - if (ctx->dynamic_base.map == NULL) { + uint64_t state_addr = ctx->dynamic_base.addr + offset; + struct gen_batch_decode_bo bo = ctx_get_bo(ctx, state_addr); + const void *state_map = bo.map; + + if (state_map == NULL) { fprintf(ctx->fp, " samplers unavailable\n"); return; } - if (offset % 32 != 0 || offset >= ctx->dynamic_base.size) { + if (offset % 32 != 0 || state_addr - bo.addr >= bo.size) { fprintf(ctx->fp, " invalid sampler state pointer\n"); return; } - uint64_t state_addr = ctx->dynamic_base.addr + offset; - const void *state_map = ctx->dynamic_base.map + offset; for (int i = 0; i < count; i++) { fprintf(ctx->fp, "sampler state %d\n", i); ctx_print_group(ctx, strct, state_addr, state_map); @@ -295,9 +292,6 @@ static void handle_media_interface_descriptor_load(struct gen_batch_decode_ctx *ctx, const uint32_t *p) { - if (ctx->dynamic_base.map == NULL) - return; - struct gen_group *inst = gen_spec_find_instruction(ctx->spec, p); struct gen_group *desc = gen_spec_find_struct(ctx->spec, "INTERFACE_DESCRIPTOR_DATA"); @@ -316,7 +310,14 @@ handle_media_interface_descriptor_load(struct gen_batch_decode_ctx *ctx, } uint64_t desc_addr = ctx->dynamic_base.addr + descriptor_offset; - const uint32_t *desc_map = ctx->dynamic_base.map + descriptor_offset; + struct gen_batch_decode_bo bo = ctx_get_bo(ctx, desc_addr); + const void *desc_map = bo.map; + + if (desc_map == NULL) { + fprintf(ctx->fp, " interface descriptors unavailable\n"); + return; + } + for (int i = 0; i < descriptor_count; i++) { fprintf(ctx->fp, "descriptor %d: %08x\n", i, descriptor_offset); @@ -640,11 +641,6 @@ decode_dynamic_state_pointers(struct gen_batch_decode_ctx *ctx, const char *struct_type, const uint32_t *p, int count) { - if (ctx->dynamic_base.map == NULL) { - fprintf(ctx->fp, " dynamic %s state unavailable\n", struct_type); - return; - } - struct gen_group *inst = gen_spec_find_instruction(ctx->spec, p); struct gen_group *state = gen_spec_find_struct(ctx->spec, struct_type); @@ -659,8 +655,15 @@ decode_dynamic_state_pointers(struct gen_batch_decode_ctx *ctx, } } - uint32_t state_addr = ctx->dynamic_base.addr + state_offset; - const uint32_t *state_map = ctx->dynamic_base.map + state_offset; + uint64_t state_addr = ctx->dynamic_base.addr + state_offset; + struct gen_batch_decode_bo bo = ctx_get_bo(ctx, state_addr); + const void *state_map = bo.map; + + if (state_map == NULL) { + fprintf(ctx->fp, " dynamic %s state unavailable\n", struct_type); + return; + } + for (int i = 0; i < count; i++) { fprintf(ctx->fp, "%s %d\n", struct_type, i); ctx_print_group(ctx, state, state_offset, state_map); diff --git a/src/intel/common/gen_decoder.h b/src/intel/common/gen_decoder.h index f2207ddf889..afbdb6a9aae 100644 --- a/src/intel/common/gen_decoder.h +++ b/src/intel/common/gen_decoder.h @@ -205,8 +205,13 @@ struct gen_batch_decode_bo { struct gen_disasm *disasm; struct gen_batch_decode_ctx { - struct gen_batch_decode_bo (*get_bo)(void *user_data, - uint64_t base_address); + /** + * Return information about the buffer containing the given address. + * + * If the given address is inside a buffer, the map pointer should be + * offset accordingly so it points at the data corresponding to address. + */ + struct gen_batch_decode_bo (*get_bo)(void *user_data, uint64_t address); unsigned (*get_state_size)(void *user_data, uint32_t offset_from_dynamic_state_base_addr); void *user_data; -- 2.30.2