From 6f5c8d0e247c876f5e4974fcbd72210fd27eb560 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Mon, 5 Sep 2022 15:49:39 -0400 Subject: [PATCH] asahi: Express VDM commands according to PowerVR Piles of unknown bits go away, as we find they're either "field present" bits or block types. And yep, the block type enum lines up between AGX and RGX. Signed-off-by: Alyssa Rosenzweig Part-of: --- src/asahi/lib/agx_ppp.h | 4 +- src/asahi/lib/cmdbuf.xml | 149 +++++++++++++++++--------- src/asahi/lib/decode.c | 96 +++++++++++++---- src/gallium/drivers/asahi/agx_state.c | 100 ++++++++++++----- 4 files changed, 246 insertions(+), 103 deletions(-) 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;