freedreno/ir3: Passthrough TCS support

Wire up support for the two intrisics to get default tess levels (which
adds new HS driver params) and add a helper to generate a passthrough
TCS for a given VS.  The passthrough TCS is cached in the VS, indexed by
patch_vertices, as the generated TCS is a function of the VS outputs and
the patch_vertices count.

Signed-off-by: Rob Clark <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19259>
This commit is contained in:
Rob Clark 2022-10-22 11:39:21 -07:00 committed by Marge Bot
parent a7290370de
commit 38c747ce3d
4 changed files with 89 additions and 0 deletions

View file

@ -2433,6 +2433,16 @@ emit_intrinsic(struct ir3_context *ctx, nir_intrinsic_instr *intr)
dst[0]->cat6.type = TYPE_U32;
__ssa_dst(dst[0]);
break;
case nir_intrinsic_load_tess_level_outer_default:
for (int i = 0; i < dest_components; i++) {
dst[i] = create_driver_param(ctx, IR3_DP_HS_DEFAULT_OUTER_LEVEL_X + i);
}
break;
case nir_intrinsic_load_tess_level_inner_default:
for (int i = 0; i < dest_components; i++) {
dst[i] = create_driver_param(ctx, IR3_DP_HS_DEFAULT_INNER_LEVEL_X + i);
}
break;
case nir_intrinsic_discard_if:
case nir_intrinsic_discard:
case nir_intrinsic_demote:

View file

@ -679,6 +679,8 @@ ir3_nir_lower_variant(struct ir3_shader_variant *so, nir_shader *s)
progress = true;
break;
case MESA_SHADER_TESS_CTRL:
NIR_PASS_V(s, nir_lower_io_to_scalar,
nir_var_shader_in | nir_var_shader_out);
NIR_PASS_V(s, ir3_nir_lower_tess_ctrl, so, so->key.tessellation);
NIR_PASS_V(s, ir3_nir_lower_to_explicit_input, so);
progress = true;
@ -940,6 +942,14 @@ ir3_nir_scan_driver_consts(struct ir3_compiler *compiler, nir_shader *shader, st
layout->num_driver_params =
MAX2(layout->num_driver_params, IR3_DP_DRAWID + 1);
break;
case nir_intrinsic_load_tess_level_outer_default:
layout->num_driver_params = MAX2(layout->num_driver_params,
IR3_DP_HS_DEFAULT_OUTER_LEVEL_W + 1);
break;
case nir_intrinsic_load_tess_level_inner_default:
layout->num_driver_params = MAX2(layout->num_driver_params,
IR3_DP_HS_DEFAULT_INNER_LEVEL_Y + 1);
break;
default:
break;
}

View file

@ -415,9 +415,58 @@ ir3_shader_get_variant(struct ir3_shader *shader,
return v;
}
struct ir3_shader *
ir3_shader_passthrough_tcs(struct ir3_shader *vs, unsigned patch_vertices)
{
assert(vs->type == MESA_SHADER_VERTEX);
assert(patch_vertices > 0);
assert(patch_vertices <= 32);
unsigned n = patch_vertices - 1;
if (!vs->vs.passthrough_tcs[n]) {
const nir_shader_compiler_options *options =
ir3_get_compiler_options(vs->compiler);
nir_shader *tcs =
nir_create_passthrough_tcs(options, vs->nir, patch_vertices);
/* Technically it is an internal shader but it is confusing to
* not have it show up in debug output
*/
tcs->info.internal = false;
nir_assign_io_var_locations(tcs, nir_var_shader_in,
&tcs->num_inputs,
tcs->info.stage);
nir_assign_io_var_locations(tcs, nir_var_shader_out,
&tcs->num_outputs,
tcs->info.stage);
NIR_PASS_V(tcs, nir_lower_system_values);
nir_shader_gather_info(tcs, nir_shader_get_entrypoint(tcs));
ir3_finalize_nir(vs->compiler, tcs);
struct ir3_shader_options ir3_options = {};
vs->vs.passthrough_tcs[n] =
ir3_shader_from_nir(vs->compiler, tcs, &ir3_options, NULL);
vs->vs.passthrough_tcs_compiled |= BITFIELD_BIT(n);
}
return vs->vs.passthrough_tcs[n];
}
void
ir3_shader_destroy(struct ir3_shader *shader)
{
if (shader->type == MESA_SHADER_VERTEX) {
u_foreach_bit (b, shader->vs.passthrough_tcs_compiled) {
ir3_shader_destroy(shader->vs.passthrough_tcs[b]);
}
}
ralloc_free(shader->nir);
mtx_destroy(&shader->variants_lock);
ralloc_free(shader);

View file

@ -73,6 +73,15 @@ enum ir3_driver_param {
IR3_DP_UCP7_W = 35,
IR3_DP_VS_COUNT = 36, /* must be aligned to vec4 */
/* TCS driver params: */
IR3_DP_HS_DEFAULT_OUTER_LEVEL_X = 0,
IR3_DP_HS_DEFAULT_OUTER_LEVEL_Y = 1,
IR3_DP_HS_DEFAULT_OUTER_LEVEL_Z = 2,
IR3_DP_HS_DEFAULT_OUTER_LEVEL_W = 3,
IR3_DP_HS_DEFAULT_INNER_LEVEL_X = 4,
IR3_DP_HS_DEFAULT_INNER_LEVEL_Y = 5,
IR3_DP_HS_COUNT = 8, /* must be aligned to vec4 */
/* fragment shader driver params: */
IR3_DP_FS_SUBGROUP_SIZE = 0,
};
@ -854,6 +863,15 @@ struct ir3_shader {
unsigned req_input_mem; /* in dwords */
unsigned req_local_mem;
} cs;
/* For vertex shaders: */
struct {
/* If we need to generate a passthrough TCS, it will be a function of
* (a) the VS and (b) the # of patch_vertices (max 32), so cache them
* in the VS keyed by # of patch_vertices-1.
*/
unsigned passthrough_tcs_compiled;
struct ir3_shader *passthrough_tcs[32];
} vs;
};
struct ir3_shader_variant *variants;
@ -939,6 +957,8 @@ ir3_shader_from_nir(struct ir3_compiler *compiler, nir_shader *nir,
struct ir3_stream_output_info *stream_output);
uint32_t ir3_trim_constlen(struct ir3_shader_variant **variants,
const struct ir3_compiler *compiler);
struct ir3_shader *
ir3_shader_passthrough_tcs(struct ir3_shader *vs, unsigned patch_vertices);
void ir3_shader_destroy(struct ir3_shader *shader);
void ir3_shader_disasm(struct ir3_shader_variant *so, uint32_t *bin, FILE *out);
uint64_t ir3_shader_outputs(const struct ir3_shader *so);