hk: make tess partitioning dynamic

no discernible difference in perf in terraintessellation. reduces tessellator
variants from 72 to 24.

before:
SHADER-DB:  - MESA_SHADER_COMPUTE shader: 2966 inst, 2310 alu, 2310 fscib, 1216 ic, 23148 bytes, 239 regs, 180 uniforms, 0 scratch, 384 threads, 17 loops, 0:0 spills:fills

after:
SHADER-DB:  - MESA_SHADER_COMPUTE shader: 3011 inst, 2343 alu, 2343 fscib, 1264 ic, 23508 bytes, 235 regs, 188 uniforms, 0 scratch, 384 threads, 17 loops, 0:0 spills:fills

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/31908>
This commit is contained in:
Alyssa Rosenzweig 2024-10-26 22:03:03 -04:00
parent d3d22039e1
commit ddf2f2f5b1
6 changed files with 24 additions and 18 deletions

View file

@ -1567,15 +1567,14 @@ agx_nir_tessellate(nir_builder *b, const void *data)
nir_def *params = nir_load_preamble(b, 1, 64, .base = 0);
nir_def *patch = nir_channel(b, nir_load_global_invocation_id(b, 32), 0);
nir_def *mode = nir_imm_int(b, key->mode);
nir_def *partitioning = nir_imm_int(b, key->partitioning);
nir_def *output_prim = nir_imm_int(b, key->output_primitive);
if (key->prim == TESS_PRIMITIVE_ISOLINES)
libagx_tess_isoline(b, params, mode, partitioning, output_prim, patch);
libagx_tess_isoline(b, params, mode, output_prim, patch);
else if (key->prim == TESS_PRIMITIVE_TRIANGLES)
libagx_tess_tri(b, params, mode, partitioning, output_prim, patch);
libagx_tess_tri(b, params, mode, output_prim, patch);
else if (key->prim == TESS_PRIMITIVE_QUADS)
libagx_tess_quad(b, params, mode, partitioning, output_prim, patch);
libagx_tess_quad(b, params, mode, output_prim, patch);
else
unreachable("invalid tess primitive");
}

View file

@ -54,8 +54,8 @@ void agx_nir_unroll_restart(struct nir_builder *b, const void *key);
struct agx_tessellator_key {
enum tess_primitive_mode prim : 8;
enum libagx_tess_output_primitive output_primitive : 8;
enum libagx_tess_partitioning partitioning : 8;
enum libagx_tess_mode mode : 8;
unsigned pad : 8;
};
static_assert(sizeof(struct agx_tessellator_key) == 4, "padded");

View file

@ -829,10 +829,11 @@ StitchTransition(private struct CHWTessellator *ctx, int baseIndexOffset,
void
libagx_tess_isoline(constant struct libagx_tess_args *p,
enum libagx_tess_mode mode,
enum libagx_tess_partitioning partitioning,
enum libagx_tess_output_primitive output_primitive,
uint patch)
{
enum libagx_tess_partitioning partitioning = p->partitioning;
bool lineDensityOdd;
bool lineDetailOdd;
TESS_FACTOR_CONTEXT lineDensityTessFactorCtx;
@ -928,10 +929,10 @@ libagx_tess_isoline(constant struct libagx_tess_args *p,
void
libagx_tess_tri(constant struct libagx_tess_args *p, enum libagx_tess_mode mode,
enum libagx_tess_partitioning partitioning,
enum libagx_tess_output_primitive output_primitive, uint patch)
{
enum libagx_tess_partitioning partitioning = p->partitioning;
global float *factors = tess_factors(p, patch);
float tessFactor_Ueq0 = factors[0];
float tessFactor_Veq0 = factors[1];
@ -1261,9 +1262,9 @@ libagx_tess_tri(constant struct libagx_tess_args *p, enum libagx_tess_mode mode,
void
libagx_tess_quad(constant struct libagx_tess_args *p,
enum libagx_tess_mode mode,
enum libagx_tess_partitioning partitioning,
enum libagx_tess_output_primitive output_primitive, uint patch)
{
enum libagx_tess_partitioning partitioning = p->partitioning;
global float *factors = tess_factors(p, patch);
float tessFactor_Ueq0 = factors[0];

View file

@ -133,5 +133,10 @@ struct libagx_tess_args {
/* Number of patches being tessellated */
uint32_t nr_patches;
/* Partitioning. This affects per-patch setup code but not the hot
* tessellation loop so we make it dynamic to reduce tessellator variants.
*/
enum libagx_tess_partitioning partitioning;
} PACKED;
AGX_STATIC_ASSERT(sizeof(struct libagx_tess_args) == 48 * 4);
AGX_STATIC_ASSERT(sizeof(struct libagx_tess_args) == 49 * 4);

View file

@ -1291,6 +1291,13 @@ hk_upload_tess_params(struct hk_cmd_buffer *cmd, struct libagx_tess_args *out,
struct hk_graphics_state *gfx = &cmd->state.gfx;
struct hk_shader *tcs = hk_only_variant(gfx->shaders[MESA_SHADER_TESS_CTRL]);
enum libagx_tess_partitioning partitioning =
gfx->tess.info.spacing == TESS_SPACING_EQUAL
? LIBAGX_TESS_PARTITIONING_INTEGER
: gfx->tess.info.spacing == TESS_SPACING_FRACTIONAL_ODD
? LIBAGX_TESS_PARTITIONING_FRACTIONAL_ODD
: LIBAGX_TESS_PARTITIONING_FRACTIONAL_EVEN;
struct libagx_tess_args args = {
.heap = hk_geometry_state(cmd),
.tcs_stride_el = tcs->info.tess.tcs_output_stride / 4,
@ -1302,6 +1309,7 @@ hk_upload_tess_params(struct hk_cmd_buffer *cmd, struct libagx_tess_args *out,
.output_patch_size = tcs->info.tess.tcs_output_patch_size,
.tcs_patch_constants = tcs->info.tess.tcs_nr_patch_outputs,
.tcs_per_vertex_outputs = tcs->info.tess.tcs_per_vertex_outputs,
.partitioning = partitioning,
};
bool with_counts = hk_tess_needs_prefix_sum(cmd, draw);
@ -1722,12 +1730,6 @@ hk_launch_tess(struct hk_cmd_buffer *cmd, struct hk_cs *cs, struct hk_draw draw)
bool ccw = info.ccw;
ccw ^= dyn->ts.domain_origin == VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT;
enum libagx_tess_partitioning partitioning =
info.spacing == TESS_SPACING_EQUAL ? LIBAGX_TESS_PARTITIONING_INTEGER
: info.spacing == TESS_SPACING_FRACTIONAL_ODD
? LIBAGX_TESS_PARTITIONING_FRACTIONAL_ODD
: LIBAGX_TESS_PARTITIONING_FRACTIONAL_EVEN;
enum libagx_tess_output_primitive prim =
info.points ? LIBAGX_TESS_OUTPUT_POINT
: ccw ? LIBAGX_TESS_OUTPUT_TRIANGLE_CCW
@ -1736,7 +1738,6 @@ hk_launch_tess(struct hk_cmd_buffer *cmd, struct hk_cs *cs, struct hk_draw draw)
struct agx_tessellator_key key = {
.prim = info.mode,
.output_primitive = prim,
.partitioning = partitioning,
};
if (with_counts) {

View file

@ -4635,6 +4635,7 @@ agx_draw_patches(struct agx_context *ctx, const struct pipe_draw_info *info,
.tcs_patch_constants = tcs->tess.nr_patch_outputs,
.tcs_per_vertex_outputs = tcs->tess.per_vertex_outputs,
.patch_coord_buffer = agx_resource(ctx->heap)->bo->va->addr,
.partitioning = partitioning,
};
memcpy(&args.tess_level_outer_default, ctx->default_outer_level,
@ -4779,7 +4780,6 @@ agx_draw_patches(struct agx_context *ctx, const struct pipe_draw_info *info,
struct agx_tessellator_key key = {
.prim = mode,
.output_primitive = prim,
.partitioning = partitioning,
};
if (with_counts) {