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;