diff --git a/src/asahi/libagx/geometry.cl b/src/asahi/libagx/geometry.cl index b9f85854e51..2c0466f0be7 100644 --- a/src/asahi/libagx/geometry.cl +++ b/src/asahi/libagx/geometry.cl @@ -758,7 +758,8 @@ libagx_prefix_sum_geom(constant struct agx_geometry_params *p) } KERNEL(1024) -libagx_prefix_sum_tess(global struct libagx_tess_args *p) +libagx_prefix_sum_tess(global struct libagx_tess_args *p, global uint *c_prims, + global uint *c_invs, uint increment_stats__2) { _libagx_prefix_sum(p->counts, p->nr_patches, 1 /* words */, 0 /* word */); @@ -786,6 +787,19 @@ libagx_prefix_sum_tess(global struct libagx_tess_args *p) desc[2] = alloc_B / elsize_B; /* start */ desc[3] = 0; /* index_bias */ desc[4] = 0; /* start_instance */ + + /* If necessary, increment clipper statistics too. This is only used when + * there's no geometry shader following us. See agx_nir_lower_gs.c for more + * info on the emulation. We just need to calculate the # of primitives + * tessellated. + */ + if (increment_stats__2) { + uint prims = p->points_mode ? total + : p->isolines ? (total / 2) + : (total / 3); + + increment_counters(c_prims, c_invs, NULL, prims); + } } uintptr_t diff --git a/src/asahi/libagx/tessellator.h b/src/asahi/libagx/tessellator.h index d8deb9de3d9..ced21ad563e 100644 --- a/src/asahi/libagx/tessellator.h +++ b/src/asahi/libagx/tessellator.h @@ -97,6 +97,7 @@ struct libagx_tess_args { */ enum libagx_tess_partitioning partitioning; uint32_t points_mode; + uint32_t isolines; /* When fed into a geometry shader, triangles should be counter-clockwise. * The tessellator always produces clockwise triangles, but we can swap @@ -104,4 +105,4 @@ struct libagx_tess_args { */ uint32_t ccw; } PACKED; -static_assert(sizeof(struct libagx_tess_args) == 35 * 4); +static_assert(sizeof(struct libagx_tess_args) == 36 * 4); diff --git a/src/asahi/vulkan/hk_cmd_draw.c b/src/asahi/vulkan/hk_cmd_draw.c index 2741ff23184..d4c408f9f30 100644 --- a/src/asahi/vulkan/hk_cmd_draw.c +++ b/src/asahi/vulkan/hk_cmd_draw.c @@ -1230,6 +1230,7 @@ hk_upload_tess_params(struct hk_cmd_buffer *cmd, struct libagx_tess_args *out, .tcs_per_vertex_outputs = tcs->info.tess.tcs_per_vertex_outputs, .partitioning = partitioning, .points_mode = gfx->tess.info.points, + .isolines = gfx->tess.info.mode == TESS_PRIMITIVE_ISOLINES, }; if (!args.points_mode && gfx->tess.info.mode != TESS_PRIMITIVE_ISOLINES) { @@ -1538,7 +1539,7 @@ hk_launch_gs_prerast(struct hk_cmd_buffer *cmd, struct hk_cs *cs, static struct agx_draw hk_launch_tess(struct hk_cmd_buffer *cmd, struct hk_cs *cs, - struct agx_draw draw) + struct agx_draw draw, uint64_t c_prims, uint64_t c_inv) { struct hk_device *dev = hk_cmd_buffer_device(cmd); struct hk_graphics_state *gfx = &cmd->state.gfx; @@ -1621,7 +1622,7 @@ hk_launch_tess(struct hk_cmd_buffer *cmd, struct hk_cs *cs, LIBAGX_TESS_MODE_COUNT, state); libagx_prefix_sum_tess(cmd, agx_1d(1024), AGX_BARRIER_ALL | AGX_PREGFX, - state); + state, c_prims, c_inv, c_prims || c_inv); libagx_tessellate(cmd, grid_tess, AGX_BARRIER_ALL | AGX_PREGFX, info.mode, LIBAGX_TESS_MODE_WITH_COUNTS, state); @@ -3373,8 +3374,6 @@ hk_ia_update(struct hk_cmd_buffer *cmd, struct agx_draw draw, /* Clipper counters depend on geom/tess outputs and must be written with the * geom/tess output. They are updated as IA counters only when geom/tess is * not used. - * - * TODO: Tessellation clipper counters not actually wired up, pending CTS. */ if (geom || tess) { c_prims = 0; @@ -3471,7 +3470,8 @@ hk_draw(struct hk_cmd_buffer *cmd, uint16_t draw_id, struct agx_draw draw_) } if (tess) { - draw = hk_launch_tess(cmd, ccs, draw); + draw = hk_launch_tess(cmd, ccs, draw, geom ? 0 : stat_c_prims, + geom ? 0 : stat_c_inv); } if (geom) { diff --git a/src/gallium/drivers/asahi/agx_state.c b/src/gallium/drivers/asahi/agx_state.c index befdd4ee5d9..158e8b60202 100644 --- a/src/gallium/drivers/asahi/agx_state.c +++ b/src/gallium/drivers/asahi/agx_state.c @@ -3907,13 +3907,14 @@ agx_ia_update(struct agx_batch *batch, const struct pipe_draw_info *info, uint64_t c_invs = agx_get_query_address( batch, ctx->pipeline_statistics[PIPE_STAT_QUERY_C_INVOCATIONS]); - /* With a geometry shader, clipper counters are written by the pre-GS kernel - * since they depend on the output on the geometry shader. Without a geometry - * shader, they are written along with IA. - * - * TODO: Broken tessellation interaction, but nobody cares. + /* With a geometry/tessellation shader, clipper counters are written by the + * pre-GS/tess prefix sum kernel since they depend on the output on the + * geometry/tessellation shader. Without a geometry/tessellation shader, + * they are written along with IA. */ - if (ctx->stage[PIPE_SHADER_GEOMETRY].shader) { + if (ctx->stage[PIPE_SHADER_GEOMETRY].shader || + ctx->stage[PIPE_SHADER_TESS_EVAL].shader) { + c_prims = 0; c_invs = 0; } @@ -4620,6 +4621,7 @@ agx_draw_patches(struct agx_context *ctx, const struct pipe_draw_info *info, .patch_coord_buffer = agx_resource(ctx->heap)->bo->va->addr, .partitioning = partitioning, .points_mode = point_mode, + .isolines = mode == TESS_PRIMITIVE_ISOLINES, }; if (!point_mode && tes->tess.primitive != TESS_PRIMITIVE_ISOLINES) { @@ -4736,10 +4738,24 @@ agx_draw_patches(struct agx_context *ctx, const struct pipe_draw_info *info, batch->uniforms.vertex_output_buffer_ptr = 0; + uint64_t c_prims = agx_get_query_address( + batch, ctx->pipeline_statistics[PIPE_STAT_QUERY_C_PRIMITIVES]); + uint64_t c_invs = agx_get_query_address( + batch, ctx->pipeline_statistics[PIPE_STAT_QUERY_C_INVOCATIONS]); + + /* If there's a geometry shader, it will increment the clipper stats. + * Otherwise, we do when tessellating. + */ + if (ctx->stage[PIPE_SHADER_GEOMETRY].shader) { + c_prims = 0; + c_invs = 0; + } + /* Generate counts, then prefix sum them, then finally tessellate. */ libagx_tessellate(batch, tess_grid, AGX_BARRIER_ALL, mode, LIBAGX_TESS_MODE_COUNT, state); - libagx_prefix_sum_tess(batch, agx_1d(1024), AGX_BARRIER_ALL, state); + libagx_prefix_sum_tess(batch, agx_1d(1024), AGX_BARRIER_ALL, state, c_prims, + c_invs, c_prims || c_invs); libagx_tessellate(batch, tess_grid, AGX_BARRIER_ALL, mode, LIBAGX_TESS_MODE_WITH_COUNTS, state); @@ -4949,6 +4965,7 @@ agx_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, ctx->pipeline_statistics[PIPE_STAT_QUERY_VS_INVOCATIONS] || ((ctx->pipeline_statistics[PIPE_STAT_QUERY_C_PRIMITIVES] || ctx->pipeline_statistics[PIPE_STAT_QUERY_C_INVOCATIONS]) && + !ctx->stage[PIPE_SHADER_TESS_EVAL].shader && !ctx->stage[PIPE_SHADER_GEOMETRY].shader))) { uint64_t ptr;