intel: Make the decoder handle STATE_BASE_ADDRESS not being a buffer.
authorKenneth Graunke <kenneth@whitecape.org>
Wed, 11 Jul 2018 17:50:16 +0000 (10:50 -0700)
committerKenneth Graunke <kenneth@whitecape.org>
Wed, 25 Jul 2018 21:43:47 +0000 (14:43 -0700)
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 <lionel.g.landwerlin@intel.com>
src/intel/common/gen_batch_decoder.c
src/intel/common/gen_decoder.h

index 727cbb80cfbf98374eaceea288eb4c9193e628a0..c6967ebc053ca91d79afdb37e014af6df40413ae 100644 (file)
@@ -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 <not valid>\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 <not valid>\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);
index f2207ddf8898512c61b3b614ddaa87e8f6e4c925..afbdb6a9aae43d276ad8ba00eaf6731c2afcee5e 100644 (file)
@@ -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;