amd: lower load_barycentric_pixel/centroid/sample in NIR

radeonsi needs to preserve interp_mode in the arg load.

Reviewed-by: Timur Kristóf <timur.kristof@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32782>
This commit is contained in:
Marek Olšák 2024-12-25 12:44:59 -05:00 committed by Marge Bot
parent a15e733a81
commit 16ab05fad1
6 changed files with 40 additions and 112 deletions

View file

@ -275,6 +275,36 @@ lower_intrinsic_to_arg(nir_builder *b, nir_instr *instr, void *state)
case nir_intrinsic_load_front_face_fsign:
replacement = ac_nir_load_arg(b, s->args, s->args->front_face);
break;
case nir_intrinsic_load_barycentric_pixel:
if (nir_intrinsic_interp_mode(intrin) == INTERP_MODE_NOPERSPECTIVE)
replacement = ac_nir_load_arg(b, s->args, s->args->linear_center);
else
replacement = ac_nir_load_arg(b, s->args, s->args->persp_center);
nir_intrinsic_set_flags(nir_instr_as_intrinsic(replacement->parent_instr),
AC_VECTOR_ARG_FLAG(AC_VECTOR_ARG_INTERP_MODE,
nir_intrinsic_interp_mode(intrin)));
break;
case nir_intrinsic_load_barycentric_centroid:
if (nir_intrinsic_interp_mode(intrin) == INTERP_MODE_NOPERSPECTIVE)
replacement = ac_nir_load_arg(b, s->args, s->args->linear_centroid);
else
replacement = ac_nir_load_arg(b, s->args, s->args->persp_centroid);
nir_intrinsic_set_flags(nir_instr_as_intrinsic(replacement->parent_instr),
AC_VECTOR_ARG_FLAG(AC_VECTOR_ARG_INTERP_MODE,
nir_intrinsic_interp_mode(intrin)));
break;
case nir_intrinsic_load_barycentric_sample:
if (nir_intrinsic_interp_mode(intrin) == INTERP_MODE_NOPERSPECTIVE)
replacement = ac_nir_load_arg(b, s->args, s->args->linear_sample);
else
replacement = ac_nir_load_arg(b, s->args, s->args->persp_sample);
nir_intrinsic_set_flags(nir_instr_as_intrinsic(replacement->parent_instr),
AC_VECTOR_ARG_FLAG(AC_VECTOR_ARG_INTERP_MODE,
nir_intrinsic_interp_mode(intrin)));
break;
case nir_intrinsic_load_barycentric_model:
replacement = ac_nir_load_arg(b, s->args, s->args->pull_model);
break;
default:
return false;
}

View file

@ -7945,21 +7945,6 @@ Temp merged_wave_info_to_mask(isel_context* ctx, unsigned i);
Temp lanecount_to_mask(isel_context* ctx, Temp count, unsigned bit_offset);
void pops_await_overlapped_waves(isel_context* ctx);
Temp
get_interp_param(isel_context* ctx, nir_intrinsic_op intrin, enum glsl_interp_mode interp)
{
bool linear = interp == INTERP_MODE_NOPERSPECTIVE;
if (intrin == nir_intrinsic_load_barycentric_pixel ||
intrin == nir_intrinsic_load_barycentric_at_offset) {
return get_arg(ctx, linear ? ctx->args->linear_center : ctx->args->persp_center);
} else if (intrin == nir_intrinsic_load_barycentric_centroid) {
return get_arg(ctx, linear ? ctx->args->linear_centroid : ctx->args->persp_centroid);
} else {
assert(intrin == nir_intrinsic_load_barycentric_sample);
return get_arg(ctx, linear ? ctx->args->linear_sample : ctx->args->persp_sample);
}
}
void
ds_ordered_count_offsets(isel_context* ctx, unsigned index_operand, unsigned wave_release,
unsigned wave_done, unsigned* offset0, unsigned* offset1)
@ -8057,32 +8042,14 @@ visit_intrinsic(isel_context* ctx, nir_intrinsic_instr* instr)
{
Builder bld(ctx->program, ctx->block);
switch (instr->intrinsic) {
case nir_intrinsic_load_barycentric_sample:
case nir_intrinsic_load_barycentric_pixel:
case nir_intrinsic_load_barycentric_centroid: {
glsl_interp_mode mode = (glsl_interp_mode)nir_intrinsic_interp_mode(instr);
Temp bary = get_interp_param(ctx, instr->intrinsic, mode);
assert(bary.size() == 2);
Temp dst = get_ssa_temp(ctx, &instr->def);
bld.copy(Definition(dst), bary);
emit_split_vector(ctx, dst, 2);
break;
}
case nir_intrinsic_load_barycentric_model: {
Temp model = get_arg(ctx, ctx->args->pull_model);
assert(model.size() == 3);
Temp dst = get_ssa_temp(ctx, &instr->def);
bld.copy(Definition(dst), model);
emit_split_vector(ctx, dst, 3);
break;
}
case nir_intrinsic_load_barycentric_at_offset: {
Temp offset = get_ssa_temp(ctx, instr->src[0].ssa);
RegClass rc = RegClass(offset.type(), 1);
Temp pos1 = bld.tmp(rc), pos2 = bld.tmp(rc);
bld.pseudo(aco_opcode::p_split_vector, Definition(pos1), Definition(pos2), offset);
Temp bary = get_interp_param(ctx, instr->intrinsic,
(glsl_interp_mode)nir_intrinsic_interp_mode(instr));
Temp bary = get_arg(ctx, nir_intrinsic_interp_mode(instr) == INTERP_MODE_NOPERSPECTIVE
? ctx->args->linear_center
: ctx->args->persp_center);
emit_interp_center(ctx, get_ssa_temp(ctx, &instr->def), bary, pos1, pos2);
break;
}

View file

@ -550,10 +550,6 @@ init_context(isel_context* ctx, nir_shader* shader)
case nir_intrinsic_load_per_vertex_input:
case nir_intrinsic_load_per_vertex_output:
case nir_intrinsic_load_vertex_id_zero_base:
case nir_intrinsic_load_barycentric_sample:
case nir_intrinsic_load_barycentric_pixel:
case nir_intrinsic_load_barycentric_model:
case nir_intrinsic_load_barycentric_centroid:
case nir_intrinsic_load_barycentric_at_offset:
case nir_intrinsic_load_interpolated_input:
case nir_intrinsic_load_local_invocation_index:

View file

@ -2657,44 +2657,12 @@ static LLVMValueRef visit_var_atomic(struct ac_nir_context *ctx, const nir_intri
return result;
}
static LLVMValueRef lookup_interp_param(struct ac_nir_context *ctx, enum glsl_interp_mode interp,
unsigned location)
{
switch (interp) {
case INTERP_MODE_FLAT:
default:
return NULL;
case INTERP_MODE_SMOOTH:
case INTERP_MODE_NONE:
if (location == INTERP_CENTER)
return ac_get_arg(&ctx->ac, ctx->args->persp_center);
else if (location == INTERP_CENTROID)
return ac_get_arg(&ctx->ac, ctx->args->persp_centroid);
else if (location == INTERP_SAMPLE)
return ac_get_arg(&ctx->ac, ctx->args->persp_sample);
break;
case INTERP_MODE_NOPERSPECTIVE:
if (location == INTERP_CENTER)
return ac_get_arg(&ctx->ac, ctx->args->linear_center);
else if (location == INTERP_CENTROID)
return ac_get_arg(&ctx->ac, ctx->args->linear_centroid);
else if (location == INTERP_SAMPLE)
return ac_get_arg(&ctx->ac, ctx->args->linear_sample);
break;
}
return NULL;
}
static LLVMValueRef barycentric_center(struct ac_nir_context *ctx, unsigned mode)
{
LLVMValueRef interp_param = lookup_interp_param(ctx, mode, INTERP_CENTER);
return LLVMBuildBitCast(ctx->ac.builder, interp_param, ctx->ac.v2i32, "");
}
static LLVMValueRef barycentric_offset(struct ac_nir_context *ctx, unsigned mode,
LLVMValueRef offset)
{
LLVMValueRef interp_param = lookup_interp_param(ctx, mode, INTERP_CENTER);
LLVMValueRef interp_param = mode == INTERP_MODE_NOPERSPECTIVE ?
ac_get_arg(&ctx->ac, ctx->args->linear_center) :
ac_get_arg(&ctx->ac, ctx->args->persp_center);
LLVMValueRef src_c0 =
ac_to_float(&ctx->ac, LLVMBuildExtractElement(ctx->ac.builder, offset, ctx->ac.i32_0, ""));
LLVMValueRef src_c1 =
@ -2730,24 +2698,6 @@ static LLVMValueRef barycentric_offset(struct ac_nir_context *ctx, unsigned mode
return LLVMBuildBitCast(ctx->ac.builder, interp_param, ctx->ac.v2i32, "");
}
static LLVMValueRef barycentric_centroid(struct ac_nir_context *ctx, unsigned mode)
{
LLVMValueRef interp_param = lookup_interp_param(ctx, mode, INTERP_CENTROID);
return LLVMBuildBitCast(ctx->ac.builder, interp_param, ctx->ac.v2i32, "");
}
static LLVMValueRef barycentric_sample(struct ac_nir_context *ctx, unsigned mode)
{
LLVMValueRef interp_param = lookup_interp_param(ctx, mode, INTERP_SAMPLE);
return LLVMBuildBitCast(ctx->ac.builder, interp_param, ctx->ac.v2i32, "");
}
static LLVMValueRef barycentric_model(struct ac_nir_context *ctx)
{
return LLVMBuildBitCast(ctx->ac.builder, ac_get_arg(&ctx->ac, ctx->args->pull_model),
ctx->ac.v3i32, "");
}
static LLVMValueRef load_interpolated_input(struct ac_nir_context *ctx, LLVMValueRef interp_param,
unsigned index, unsigned comp_start,
unsigned num_components, unsigned bitsize,
@ -3060,18 +3010,6 @@ static bool visit_intrinsic(struct ac_nir_context *ctx, nir_intrinsic_instr *ins
result = visit_var_atomic(ctx, instr, ptr, 1);
break;
}
case nir_intrinsic_load_barycentric_pixel:
result = barycentric_center(ctx, nir_intrinsic_interp_mode(instr));
break;
case nir_intrinsic_load_barycentric_centroid:
result = barycentric_centroid(ctx, nir_intrinsic_interp_mode(instr));
break;
case nir_intrinsic_load_barycentric_sample:
result = barycentric_sample(ctx, nir_intrinsic_interp_mode(instr));
break;
case nir_intrinsic_load_barycentric_model:
result = barycentric_model(ctx);
break;
case nir_intrinsic_load_barycentric_at_offset: {
LLVMValueRef offset = ac_to_float(&ctx->ac, get_src(ctx, instr->src[0]));
result = barycentric_offset(ctx, nir_intrinsic_interp_mode(instr), offset);

View file

@ -15,16 +15,10 @@
#include <stdbool.h>
struct nir_shader;
struct nir_variable;
struct ac_llvm_context;
struct ac_shader_abi;
struct ac_shader_args;
/* Interpolation locations */
#define INTERP_CENTER 0
#define INTERP_CENTROID 1
#define INTERP_SAMPLE 2
static inline unsigned ac_llvm_reg_index_soa(unsigned index, unsigned chan)
{
return (index * 4) + chan;

View file

@ -66,8 +66,11 @@ static void scan_io_usage(const nir_shader *nir, struct si_shader_info *info,
nir_instr *src_instr = intr->src[0].ssa->parent_instr;
if (src_instr->type == nir_instr_type_intrinsic) {
nir_intrinsic_instr *baryc = nir_instr_as_intrinsic(src_instr);
if (nir_intrinsic_infos[baryc->intrinsic].index_map[NIR_INTRINSIC_INTERP_MODE] > 0)
if (nir_intrinsic_has_interp_mode(baryc))
interp = nir_intrinsic_interp_mode(baryc);
else if (nir_intrinsic_has_flags(baryc) &&
AC_VECTOR_ARG_FLAG_GET_NAME(baryc) == AC_VECTOR_ARG_INTERP_MODE)
interp = AC_VECTOR_ARG_FLAG_GET_VALUE(baryc);
else
unreachable("unknown barycentric intrinsic");
} else {