diff --git a/src/asahi/lib/agx_ppp.h b/src/asahi/lib/agx_ppp.h
index 2b38f7f054c..ef822d9bfdc 100644
--- a/src/asahi/lib/agx_ppp.h
+++ b/src/asahi/lib/agx_ppp.h
@@ -129,13 +129,13 @@ agx_ppp_fini(uint8_t **out, struct agx_ppp_update *ppp)
assert(ppp->gpu_base < (1ull << 40));
assert(size_words < (1ull << 24));
- agx_pack(*out, RECORD, cfg) {
+ agx_pack(*out, PPP_STATE, cfg) {
cfg.pointer_hi = (ppp->gpu_base >> 32);
cfg.pointer_lo = (uint32_t) ppp->gpu_base;
cfg.size_words = size_words;
};
- *out += AGX_RECORD_LENGTH;
+ *out += AGX_PPP_STATE_LENGTH;
}
#endif
diff --git a/src/asahi/lib/cmdbuf.xml b/src/asahi/lib/cmdbuf.xml
index 50700580f61..99f7abec04d 100644
--- a/src/asahi/lib/cmdbuf.xml
+++ b/src/asahi/lib/cmdbuf.xml
@@ -554,45 +554,19 @@
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
@@ -601,21 +575,90 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/asahi/lib/decode.c b/src/asahi/lib/decode.c
index 0f3f36f252c..4bb88f83850 100644
--- a/src/asahi/lib/decode.c
+++ b/src/asahi/lib/decode.c
@@ -464,24 +464,19 @@ static unsigned
agxdecode_cmd(const uint8_t *map, bool verbose)
{
if (map[0] == 0x02 && map[1] == 0x10 && map[2] == 0x00 && map[3] == 0x00) {
+ /* XXX: This is a CDM command not a VDM one */
agx_unpack(agxdecode_dump_stream, map, LAUNCH, cmd);
agxdecode_stateful(cmd.pipeline, "Pipeline", agxdecode_pipeline, verbose);
DUMP_UNPACKED(LAUNCH, cmd, "Launch\n");
return AGX_LAUNCH_LENGTH;
- } else if (map[0] == 0x2E && map[1] == 0x00 && map[2] == 0x00 && map[3] == 0x40) {
- agx_unpack(agxdecode_dump_stream, map, BIND_VERTEX_PIPELINE, cmd);
- agxdecode_stateful(cmd.pipeline, "Pipeline", agxdecode_pipeline, verbose);
- DUMP_UNPACKED(BIND_VERTEX_PIPELINE, cmd, "Bind vertex pipeline\n");
- return AGX_BIND_VERTEX_PIPELINE_LENGTH;
- } else if (map[3] == 0x40) {
- DUMP_CL(INDEXED_DRAW, map, "Indexed Draw");
- return AGX_INDEXED_DRAW_LENGTH;
- } else if (map[3] == 0x61) {
- DUMP_CL(DRAW, map, "Draw");
- return AGX_DRAW_LENGTH;
- } else if (map[2] == 0x00 && map[3] == 0x00) {
- /* No need to explicitly dump the record */
- agx_unpack(agxdecode_dump_stream, map, RECORD, cmd);
+ }
+
+ /* Bits 29-31 contain the block type */
+ enum agx_vdm_block_type block_type = (map[3] >> 5);
+
+ switch (block_type) {
+ case AGX_VDM_BLOCK_TYPE_PPP_STATE_UPDATE: {
+ agx_unpack(agxdecode_dump_stream, map, PPP_STATE, cmd);
uint64_t address = (((uint64_t) cmd.pointer_hi) << 32) | cmd.pointer_lo;
struct agx_bo *mem = agxdecode_find_mapped_gpu_mem_containing(address);
@@ -489,15 +484,74 @@ agxdecode_cmd(const uint8_t *map, bool verbose)
if (mem)
agxdecode_record(address, cmd.size_words * 4, verbose);
else
- DUMP_UNPACKED(RECORD, cmd, "Non-existant record (XXX)\n");
+ DUMP_UNPACKED(PPP_STATE, cmd, "Non-existant record (XXX)\n");
- return AGX_RECORD_LENGTH;
- } 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 AGX_PPP_STATE_LENGTH;
+ }
+
+ case AGX_VDM_BLOCK_TYPE_VDM_STATE_UPDATE: {
+ size_t length = AGX_VDM_STATE_LENGTH;
+ agx_unpack(agxdecode_dump_stream, map, VDM_STATE, hdr);
+ map += AGX_VDM_STATE_LENGTH;
+
+#define VDM_PRINT(header_name, STRUCT_NAME, human) \
+ if (hdr.header_name##_present) { \
+ DUMP_CL(VDM_STATE_##STRUCT_NAME, map, human); \
+ map += AGX_VDM_STATE_##STRUCT_NAME##_LENGTH; \
+ length += AGX_VDM_STATE_##STRUCT_NAME##_LENGTH; \
+ }
+
+ VDM_PRINT(restart_index, RESTART_INDEX, "Restart index");
+ VDM_PRINT(vertex_shader_word_0, VERTEX_SHADER_WORD_0, "Vertex shader word 0");
+
+ if (hdr.vertex_shader_word_1_present) {
+ agx_unpack(agxdecode_dump_stream, map, VDM_STATE_VERTEX_SHADER_WORD_1,
+ word_1);
+ fprintf(agxdecode_dump_stream, "Pipeline %X\n", (uint32_t) word_1.pipeline);
+ agxdecode_stateful(word_1.pipeline, "Pipeline", agxdecode_pipeline, verbose);
+ }
+
+ VDM_PRINT(vertex_shader_word_1, VERTEX_SHADER_WORD_1, "Vertex shader word 1");
+ VDM_PRINT(vertex_outputs, VERTEX_OUTPUTS, "Vertex outputs");
+ VDM_PRINT(vertex_unknown, VERTEX_UNKNOWN, "Vertex unknown");
+
+#undef VDM_PRINT
+ return ALIGN_POT(length, 8);
+ }
+
+ case AGX_VDM_BLOCK_TYPE_INDEX_LIST: {
+ size_t length = AGX_INDEX_LIST_LENGTH;
+ agx_unpack(agxdecode_dump_stream, map, INDEX_LIST, hdr);
+ DUMP_UNPACKED(INDEX_LIST, hdr, "Index List\n");
+ map += AGX_INDEX_LIST_LENGTH;
+
+#define IDX_PRINT(header_name, STRUCT_NAME, human) \
+ if (hdr.header_name##_present) { \
+ DUMP_CL(INDEX_LIST_##STRUCT_NAME, map, human); \
+ map += AGX_INDEX_LIST_##STRUCT_NAME##_LENGTH; \
+ length += AGX_INDEX_LIST_##STRUCT_NAME##_LENGTH; \
+ }
+
+ IDX_PRINT(index_buffer, BUFFER_LO, "Index buffer");
+ IDX_PRINT(index_buffer_size, BUFFER_SIZE, "Index buffer size");
+ IDX_PRINT(index_count, COUNT, "Index count");
+ IDX_PRINT(instance_count, INSTANCES, "Instance count");
+ IDX_PRINT(start, START, "Start");
+
+#undef IDX_PRINT
+ return ALIGN_POT(length, 8);
+ }
+
+ case AGX_VDM_BLOCK_TYPE_STREAM_TERMINATE: {
+ DUMP_CL(STREAM_TERMINATE, map, "Stream Terminate");
return STATE_DONE;
- } else {
- return 0;
+ }
+
+ default:
+ fprintf(agxdecode_dump_stream, "Unknown VDM block type: %u\n",
+ block_type);
+ hexdump(agxdecode_dump_stream, map, 8, false);
+ return 8;
}
}
diff --git a/src/gallium/drivers/asahi/agx_state.c b/src/gallium/drivers/asahi/agx_state.c
index 94f31e8d62c..917af844688 100644
--- a/src/gallium/drivers/asahi/agx_state.c
+++ b/src/gallium/drivers/asahi/agx_state.c
@@ -1512,18 +1512,40 @@ agx_encode_state(struct agx_context *ctx, uint8_t *out,
#define IS_DIRTY(ST) !!(ctx->dirty & AGX_DIRTY_##ST)
if (IS_DIRTY(VS)) {
- unsigned tex_count = ctx->stage[PIPE_SHADER_VERTEX].texture_count;
- agx_pack(out, BIND_VERTEX_PIPELINE, cfg) {
- cfg.pipeline = agx_build_pipeline(ctx, ctx->vs, PIPE_SHADER_VERTEX);
- cfg.output_count_1 = ctx->vs->info.varyings.vs.nr_index;
- cfg.output_count_2 = cfg.output_count_1;
+ agx_pack(out, VDM_STATE, cfg) {
+ cfg.vertex_shader_word_0_present = true;
+ cfg.vertex_shader_word_1_present = true;
+ cfg.vertex_outputs_present = true;
+ cfg.vertex_unknown_present = true;
+ }
+ out += AGX_VDM_STATE_LENGTH;
+ unsigned tex_count = ctx->stage[PIPE_SHADER_VERTEX].texture_count;
+ agx_pack(out, VDM_STATE_VERTEX_SHADER_WORD_0, cfg) {
cfg.groups_of_8_immediate_textures = DIV_ROUND_UP(tex_count, 8);
cfg.groups_of_4_samplers = DIV_ROUND_UP(tex_count, 4);
+ }
+ out += AGX_VDM_STATE_VERTEX_SHADER_WORD_0_LENGTH;
+
+ agx_pack(out, VDM_STATE_VERTEX_SHADER_WORD_1, cfg) {
+ cfg.pipeline = agx_build_pipeline(ctx, ctx->vs, PIPE_SHADER_VERTEX);
+ }
+ out += AGX_VDM_STATE_VERTEX_SHADER_WORD_1_LENGTH;
+
+ agx_pack(out, VDM_STATE_VERTEX_OUTPUTS, cfg) {
+ cfg.output_count_1 = ctx->vs->info.varyings.vs.nr_index;
+ cfg.output_count_2 = cfg.output_count_1;
+ }
+ out += AGX_VDM_STATE_VERTEX_OUTPUTS_LENGTH;
+
+ agx_pack(out, VDM_STATE_VERTEX_UNKNOWN, cfg) {
cfg.more_than_4_textures = tex_count >= 4;
}
+ out += AGX_VDM_STATE_VERTEX_UNKNOWN_LENGTH;
- out += AGX_BIND_VERTEX_PIPELINE_LENGTH;
+ /* Pad up to a multiple of 8 bytes */
+ memset(out, 0, 4);
+ out += 4;
}
struct agx_pool *pool = &ctx->batch->pool;
@@ -1793,39 +1815,63 @@ agx_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info,
enum agx_primitive prim = agx_primitive_for_pipe(info->mode);
unsigned idx_size = info->index_size;
+ uint64_t ib = idx_size ? agx_index_buffer_ptr(batch, draws, info) : 0;
if (idx_size) {
- uint64_t ib = agx_index_buffer_ptr(batch, draws, info);
-
/* Index sizes are encoded logarithmically */
STATIC_ASSERT(__builtin_ctz(1) == AGX_INDEX_SIZE_U8);
STATIC_ASSERT(__builtin_ctz(2) == AGX_INDEX_SIZE_U16);
STATIC_ASSERT(__builtin_ctz(4) == AGX_INDEX_SIZE_U32);
assert((idx_size == 1) || (idx_size == 2) || (idx_size == 4));
- agx_pack(out, INDEXED_DRAW, cfg) {
- cfg.restart_index = info->restart_index;
- cfg.primitive = prim;
+ agx_pack(out, VDM_STATE, cfg) cfg.restart_index_present = true;
+ out += AGX_VDM_STATE_LENGTH;
+
+ agx_pack(out, VDM_STATE_RESTART_INDEX, cfg) {
+ cfg.value = info->restart_index;
+ }
+ out += AGX_VDM_STATE_RESTART_INDEX_LENGTH;
+ }
+
+ agx_pack(out, INDEX_LIST, cfg) {
+ cfg.primitive = prim;
+ cfg.index_count_present = true;
+ cfg.instance_count_present = true;
+ cfg.start_present = true;
+
+ if (idx_size) {
cfg.restart_enable = info->primitive_restart;
- cfg.index_size = __builtin_ctz(idx_size);
- cfg.index_buffer_lo = (ib & BITFIELD_MASK(32));
cfg.index_buffer_hi = (ib >> 32);
- cfg.index_buffer_size = ALIGN_POT(draws->count * idx_size, 4);
- cfg.index_count = draws->count;
- cfg.instance_count = info->instance_count;
- cfg.base_vertex = draws->index_bias;
- };
+ cfg.index_size = __builtin_ctz(idx_size);
+ cfg.index_buffer_present = true;
+ cfg.index_buffer_size_present = true;
+ }
+ }
+ out += AGX_INDEX_LIST_LENGTH;
- out += AGX_INDEXED_DRAW_LENGTH;
- } else {
- agx_pack(out, DRAW, cfg) {
- cfg.primitive = prim;
- cfg.vertex_start = draws->start;
- cfg.vertex_count = draws->count;
- cfg.instance_count = info->instance_count;
- };
+ if (idx_size) {
+ agx_pack(out, INDEX_LIST_BUFFER_LO, cfg) {
+ cfg.buffer_lo = ib & BITFIELD_MASK(32);
+ }
+ out += AGX_INDEX_LIST_BUFFER_LO_LENGTH;
+ }
- out += AGX_DRAW_LENGTH;
+ agx_pack(out, INDEX_LIST_COUNT, cfg) cfg.count = draws->count;
+ out += AGX_INDEX_LIST_COUNT_LENGTH;
+
+ agx_pack(out, INDEX_LIST_INSTANCES, cfg) cfg.count = info->instance_count;
+ out += AGX_INDEX_LIST_INSTANCES_LENGTH;
+
+ agx_pack(out, INDEX_LIST_START, cfg) {
+ cfg.start = idx_size ? draws->index_bias : draws->start;
+ }
+ out += AGX_INDEX_LIST_START_LENGTH;
+
+ if (idx_size) {
+ agx_pack(out, INDEX_LIST_BUFFER_SIZE, cfg) {
+ cfg.size = ALIGN_POT(draws->count * idx_size, 4);
+ }
+ out += AGX_INDEX_LIST_BUFFER_SIZE_LENGTH;
}
batch->encoder_current = out;