asahi: Fix BIND_PIPELINE sizing and alignment

Fix a bug in BIND_PIPELINE XML reported by Dougall, which cleans up
a bit of both decoder and driver.

Instead of...

   * 17 bytes BIND_PIPELINE  (17)
   * An unused 8 byte record (25)
   * A set of N 8 byte records (25 + 8 * N)
   * Oops, 1 byte too many! One just disappeared (24 + 8 * N)

It seems to instead be

   * 24 bytes BIND_PIPELINE (24)
   * A set of N 8 byte records (24 + 8 * N)

without the sentinel record. These means the 8 byte records themselves
are shuffled, with the high byte of the pointers split from the low
word, but that's less gross than an off-by-one.

It's still not clear what the last 8 bytes of the BIND_VERTEX_PIPELINE
structure mean, or the last 4 byte of the BIND_FRAGMENT_PIPELINE
structure which seems to be a bit shorter.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13784>
This commit is contained in:
Alyssa Rosenzweig 2021-11-13 14:52:52 -05:00 committed by Marge Bot
parent 3b108393a2
commit 81d22da6de
3 changed files with 25 additions and 36 deletions

View File

@ -398,9 +398,8 @@
</struct>
<!--- Command to bind a vertex pipeline, followed by subcommands. Counts are
specified in 32-bit word units. Intepretation per-shader stage.
Probably actually 17 bytes. -->
<struct name="Bind pipeline" size="16">
specified in 32-bit word units. Intepretation per-shader stage. -->
<struct name="Bind pipeline" size="24">
<field name="Tag" size="32" start="0:0" type="hex" default="0x4000002e">
<value name="AGX_BIND_PIPELINE_VERTEX" value="0x4000002e"/>
<value name="AGX_BIND_PIPELINE_FRAGMENT" value="0x800000"/>
@ -418,13 +417,16 @@
<field name="VS Output count 1" size="8" start="3:0" type="uint" default="0"/>
<field name="VS Output count 2" size="8" start="3:8" type="uint" default="0"/>
<field name="Padding 2" size="16" start="3:16" type="hex" default="0x0"/>
<field name="Unk 3" size="32" start="5:0" type="address"/> <!-- C020000 -->
</struct>
<!-- Subcommands are packed inside sized records -->
<struct name="Record" size="8">
<field name="Size (words)" size="8" start="0:0" type="uint"/>
<field name="Tag" size="16" start="0:8" type="hex" default="0x0000"/>
<field name="Data" size="40" start="0:24" type="address"/>
<field name="Pointer (hi)" size="8" start="0:0" type="hex"/>
<field name="Size (words)" size="8" start="0:8" type="uint"/>
<field name="Tag" size="16" start="0:16" type="hex" default="0x0000"/>
<field name="Pointer (lo)" size="32" start="0:32" type="address"/>
</struct>
<!--- Command to issue a direct non-indexed draw -->

View File

@ -354,7 +354,7 @@ agxdecode_record(uint64_t va, size_t size, bool verbose)
assert(size == AGX_CULL_LENGTH);
DUMP_CL(CULL, map, "Cull");
} else if (tag == 0x800000) {
assert(size == (AGX_BIND_PIPELINE_LENGTH + 4));
assert(size == (AGX_BIND_PIPELINE_LENGTH - 4));
agx_unpack(agxdecode_dump_stream, map, BIND_PIPELINE, cmd);
agxdecode_stateful(cmd.pipeline, "Pipeline", agxdecode_pipeline, verbose);
@ -394,35 +394,24 @@ agxdecode_cmd(const uint8_t *map, bool verbose)
agx_unpack(agxdecode_dump_stream, map, BIND_PIPELINE, cmd);
agxdecode_stateful(cmd.pipeline, "Pipeline", agxdecode_pipeline, verbose);
DUMP_UNPACKED(BIND_PIPELINE, cmd, "Bind vertex pipeline\n");
/* Random unaligned null byte, it's pretty awful.. */
if (map[AGX_BIND_PIPELINE_LENGTH]) {
fprintf(agxdecode_dump_stream, "Unk unaligned %X\n",
map[AGX_BIND_PIPELINE_LENGTH]);
}
return AGX_BIND_PIPELINE_LENGTH + 1;
} else if (map[1] == 0xc0 && map[2] == 0x61) {
DUMP_CL(DRAW, map - 1, "Draw");
return AGX_BIND_PIPELINE_LENGTH;
} else if (map[2] == 0xc0 && map[3] == 0x61) {
DUMP_CL(DRAW, map, "Draw");
return AGX_DRAW_LENGTH;
} else if (map[1] == 0x00 && map[2] == 0x00) {
} else if (map[2] == 0x00 && map[3] == 0x00) {
/* No need to explicitly dump the record */
agx_unpack(agxdecode_dump_stream, map, RECORD, cmd);
/* XXX: Why? */
if (pipeline_base && ((cmd.data >> 32) == 0)) {
cmd.data |= pipeline_base & 0xFF00000000ull;
}
struct agx_bo *mem = agxdecode_find_mapped_gpu_mem_containing(cmd.data);
uint64_t address = (((uint64_t) cmd.pointer_hi) << 32) | cmd.pointer_lo;
struct agx_bo *mem = agxdecode_find_mapped_gpu_mem_containing(address);
if (mem)
agxdecode_record(cmd.data, cmd.size_words * 4, verbose);
agxdecode_record(address, cmd.size_words * 4, verbose);
else
DUMP_UNPACKED(RECORD, cmd, "Non-existant record (XXX)\n");
return AGX_RECORD_LENGTH;
} else if (map[0] == 0 && map[1] == 0 && map[2] == 0xC0 && map[3] == 0x00) {
} else if (map[1] == 0 && map[2] == 0 && map[3] == 0xC0 && map[4] == 0x00) {
ASSERTED unsigned zero[4] = { 0 };
assert(memcmp(map + 4, zero, sizeof(zero)) == 0);
return STATE_DONE;

View File

@ -1432,9 +1432,13 @@ agx_push_record(uint8_t **out, unsigned size_words, uint64_t ptr)
assert(ptr < (1ull << 40));
assert(size_words < (1ull << 24));
uint64_t value = (size_words | (ptr << 24));
memcpy(*out, &value, sizeof(value));
*out += sizeof(value);
agx_pack(*out, RECORD, cfg) {
cfg.pointer_hi = (ptr >> 32);
cfg.pointer_lo = (uint32_t) ptr;
cfg.size_words = size_words;
};
*out += AGX_RECORD_LENGTH;
}
static uint8_t *
@ -1451,17 +1455,11 @@ agx_encode_state(struct agx_context *ctx, uint8_t *out,
cfg.texture_count = ctx->stage[PIPE_SHADER_VERTEX].texture_count;
}
/* yes, it's really 17 bytes */
out += AGX_BIND_PIPELINE_LENGTH;
*(out++) = 0x0;
struct agx_pool *pool = &ctx->batch->pool;
struct agx_ptr zero = agx_pool_alloc_aligned(pool, 16, 256);
memset(zero.cpu, 0, 16);
bool reads_tib = ctx->fs->info.reads_tib;
agx_push_record(&out, 0, zero.gpu);
agx_push_record(&out, 5, demo_interpolation(ctx->fs, pool));
agx_push_record(&out, 5, demo_launch_fragment(ctx, pool, pipeline_fragment, varyings, ctx->fs->info.varyings.nr_descs));
agx_push_record(&out, 4, demo_linkage(ctx->vs, pool));
@ -1480,7 +1478,7 @@ agx_encode_state(struct agx_context *ctx, uint8_t *out,
agx_push_record(&out, 3, demo_unk12(pool));
agx_push_record(&out, 2, agx_pool_upload(pool, ctx->rast->cull, sizeof(ctx->rast->cull)));
return (out - 1); // XXX: alignment fixup, or something
return out;
}
static enum agx_primitive