ac/radeonsi: add lookup_interp_param and load_sample_position to the abi

This will enable the interpolateAt builtins to work on the radeonsi
nir backend.

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
This commit is contained in:
Timothy Arceri
2018-01-14 20:54:20 +11:00
parent 97058168a4
commit d185190222
3 changed files with 44 additions and 29 deletions

View File

@@ -3975,9 +3975,11 @@ static LLVMValueRef visit_var_atomic(struct nir_to_llvm_context *ctx,
return result; return result;
} }
static LLVMValueRef lookup_interp_param(struct nir_to_llvm_context *ctx, static LLVMValueRef lookup_interp_param(struct ac_shader_abi *abi,
enum glsl_interp_mode interp, unsigned location) enum glsl_interp_mode interp, unsigned location)
{ {
struct nir_to_llvm_context *ctx = nir_to_llvm_context_from_abi(abi);
switch (interp) { switch (interp) {
case INTERP_MODE_FLAT: case INTERP_MODE_FLAT:
default: default:
@@ -4003,9 +4005,11 @@ static LLVMValueRef lookup_interp_param(struct nir_to_llvm_context *ctx,
return NULL; return NULL;
} }
static LLVMValueRef load_sample_position(struct nir_to_llvm_context *ctx, static LLVMValueRef load_sample_position(struct ac_shader_abi *abi,
LLVMValueRef sample_id) LLVMValueRef sample_id)
{ {
struct nir_to_llvm_context *ctx = nir_to_llvm_context_from_abi(abi);
LLVMValueRef result; LLVMValueRef result;
LLVMValueRef ptr = ac_build_gep0(&ctx->ac, ctx->ring_offsets, LLVMConstInt(ctx->ac.i32, RING_PS_SAMPLE_POSITIONS, false)); LLVMValueRef ptr = ac_build_gep0(&ctx->ac, ctx->ring_offsets, LLVMConstInt(ctx->ac.i32, RING_PS_SAMPLE_POSITIONS, false));
@@ -4051,7 +4055,7 @@ static LLVMValueRef load_sample_mask_in(struct ac_nir_context *ctx)
return result; return result;
} }
static LLVMValueRef visit_interp(struct nir_to_llvm_context *ctx, static LLVMValueRef visit_interp(struct ac_nir_context *ctx,
const nir_intrinsic_instr *instr) const nir_intrinsic_instr *instr)
{ {
LLVMValueRef result[4]; LLVMValueRef result[4];
@@ -4069,33 +4073,33 @@ static LLVMValueRef visit_interp(struct nir_to_llvm_context *ctx,
case nir_intrinsic_interp_var_at_sample: case nir_intrinsic_interp_var_at_sample:
case nir_intrinsic_interp_var_at_offset: case nir_intrinsic_interp_var_at_offset:
location = INTERP_CENTER; location = INTERP_CENTER;
src0 = get_src(ctx->nir, instr->src[0]); src0 = get_src(ctx, instr->src[0]);
break; break;
default: default:
break; break;
} }
if (instr->intrinsic == nir_intrinsic_interp_var_at_offset) { if (instr->intrinsic == nir_intrinsic_interp_var_at_offset) {
src_c0 = ac_to_float(&ctx->ac, LLVMBuildExtractElement(ctx->builder, src0, ctx->ac.i32_0, "")); src_c0 = ac_to_float(&ctx->ac, LLVMBuildExtractElement(ctx->ac.builder, src0, ctx->ac.i32_0, ""));
src_c1 = ac_to_float(&ctx->ac, LLVMBuildExtractElement(ctx->builder, src0, ctx->ac.i32_1, "")); src_c1 = ac_to_float(&ctx->ac, LLVMBuildExtractElement(ctx->ac.builder, src0, ctx->ac.i32_1, ""));
} else if (instr->intrinsic == nir_intrinsic_interp_var_at_sample) { } else if (instr->intrinsic == nir_intrinsic_interp_var_at_sample) {
LLVMValueRef sample_position; LLVMValueRef sample_position;
LLVMValueRef halfval = LLVMConstReal(ctx->ac.f32, 0.5f); LLVMValueRef halfval = LLVMConstReal(ctx->ac.f32, 0.5f);
/* fetch sample ID */ /* fetch sample ID */
sample_position = load_sample_position(ctx, src0); sample_position = ctx->abi->load_sample_position(ctx->abi, src0);
src_c0 = LLVMBuildExtractElement(ctx->builder, sample_position, ctx->ac.i32_0, ""); src_c0 = LLVMBuildExtractElement(ctx->ac.builder, sample_position, ctx->ac.i32_0, "");
src_c0 = LLVMBuildFSub(ctx->builder, src_c0, halfval, ""); src_c0 = LLVMBuildFSub(ctx->ac.builder, src_c0, halfval, "");
src_c1 = LLVMBuildExtractElement(ctx->builder, sample_position, ctx->ac.i32_1, ""); src_c1 = LLVMBuildExtractElement(ctx->ac.builder, sample_position, ctx->ac.i32_1, "");
src_c1 = LLVMBuildFSub(ctx->builder, src_c1, halfval, ""); src_c1 = LLVMBuildFSub(ctx->ac.builder, src_c1, halfval, "");
} }
interp_param = lookup_interp_param(ctx, instr->variables[0]->var->data.interpolation, location); interp_param = ctx->abi->lookup_interp_param(ctx->abi, instr->variables[0]->var->data.interpolation, location);
attr_number = LLVMConstInt(ctx->ac.i32, input_index, false); attr_number = LLVMConstInt(ctx->ac.i32, input_index, false);
if (location == INTERP_CENTER) { if (location == INTERP_CENTER) {
LLVMValueRef ij_out[2]; LLVMValueRef ij_out[2];
LLVMValueRef ddxy_out = emit_ddxy_interp(ctx->nir, interp_param); LLVMValueRef ddxy_out = emit_ddxy_interp(ctx, interp_param);
/* /*
* take the I then J parameters, and the DDX/Y for it, and * take the I then J parameters, and the DDX/Y for it, and
@@ -4108,24 +4112,24 @@ static LLVMValueRef visit_interp(struct nir_to_llvm_context *ctx,
for (unsigned i = 0; i < 2; i++) { for (unsigned i = 0; i < 2; i++) {
LLVMValueRef ix_ll = LLVMConstInt(ctx->ac.i32, i, false); LLVMValueRef ix_ll = LLVMConstInt(ctx->ac.i32, i, false);
LLVMValueRef iy_ll = LLVMConstInt(ctx->ac.i32, i + 2, false); LLVMValueRef iy_ll = LLVMConstInt(ctx->ac.i32, i + 2, false);
LLVMValueRef ddx_el = LLVMBuildExtractElement(ctx->builder, LLVMValueRef ddx_el = LLVMBuildExtractElement(ctx->ac.builder,
ddxy_out, ix_ll, ""); ddxy_out, ix_ll, "");
LLVMValueRef ddy_el = LLVMBuildExtractElement(ctx->builder, LLVMValueRef ddy_el = LLVMBuildExtractElement(ctx->ac.builder,
ddxy_out, iy_ll, ""); ddxy_out, iy_ll, "");
LLVMValueRef interp_el = LLVMBuildExtractElement(ctx->builder, LLVMValueRef interp_el = LLVMBuildExtractElement(ctx->ac.builder,
interp_param, ix_ll, ""); interp_param, ix_ll, "");
LLVMValueRef temp1, temp2; LLVMValueRef temp1, temp2;
interp_el = LLVMBuildBitCast(ctx->builder, interp_el, interp_el = LLVMBuildBitCast(ctx->ac.builder, interp_el,
ctx->ac.f32, ""); ctx->ac.f32, "");
temp1 = LLVMBuildFMul(ctx->builder, ddx_el, src_c0, ""); temp1 = LLVMBuildFMul(ctx->ac.builder, ddx_el, src_c0, "");
temp1 = LLVMBuildFAdd(ctx->builder, temp1, interp_el, ""); temp1 = LLVMBuildFAdd(ctx->ac.builder, temp1, interp_el, "");
temp2 = LLVMBuildFMul(ctx->builder, ddy_el, src_c1, ""); temp2 = LLVMBuildFMul(ctx->ac.builder, ddy_el, src_c1, "");
temp2 = LLVMBuildFAdd(ctx->builder, temp2, temp1, ""); temp2 = LLVMBuildFAdd(ctx->ac.builder, temp2, temp1, "");
ij_out[i] = LLVMBuildBitCast(ctx->builder, ij_out[i] = LLVMBuildBitCast(ctx->ac.builder,
temp2, ctx->ac.i32, ""); temp2, ctx->ac.i32, "");
} }
interp_param = ac_build_gather_values(&ctx->ac, ij_out, 2); interp_param = ac_build_gather_values(&ctx->ac, ij_out, 2);
@@ -4136,21 +4140,21 @@ static LLVMValueRef visit_interp(struct nir_to_llvm_context *ctx,
LLVMValueRef llvm_chan = LLVMConstInt(ctx->ac.i32, chan, false); LLVMValueRef llvm_chan = LLVMConstInt(ctx->ac.i32, chan, false);
if (interp_param) { if (interp_param) {
interp_param = LLVMBuildBitCast(ctx->builder, interp_param = LLVMBuildBitCast(ctx->ac.builder,
interp_param, ctx->ac.v2f32, ""); interp_param, ctx->ac.v2f32, "");
LLVMValueRef i = LLVMBuildExtractElement( LLVMValueRef i = LLVMBuildExtractElement(
ctx->builder, interp_param, ctx->ac.i32_0, ""); ctx->ac.builder, interp_param, ctx->ac.i32_0, "");
LLVMValueRef j = LLVMBuildExtractElement( LLVMValueRef j = LLVMBuildExtractElement(
ctx->builder, interp_param, ctx->ac.i32_1, ""); ctx->ac.builder, interp_param, ctx->ac.i32_1, "");
result[chan] = ac_build_fs_interp(&ctx->ac, result[chan] = ac_build_fs_interp(&ctx->ac,
llvm_chan, attr_number, llvm_chan, attr_number,
ctx->abi.prim_mask, i, j); ctx->abi->prim_mask, i, j);
} else { } else {
result[chan] = ac_build_fs_interp_mov(&ctx->ac, result[chan] = ac_build_fs_interp_mov(&ctx->ac,
LLVMConstInt(ctx->ac.i32, 2, false), LLVMConstInt(ctx->ac.i32, 2, false),
llvm_chan, attr_number, llvm_chan, attr_number,
ctx->abi.prim_mask); ctx->abi->prim_mask);
} }
} }
return ac_build_varying_gather_values(&ctx->ac, result, instr->num_components, return ac_build_varying_gather_values(&ctx->ac, result, instr->num_components,
@@ -4473,7 +4477,7 @@ static void visit_intrinsic(struct ac_nir_context *ctx,
case nir_intrinsic_interp_var_at_centroid: case nir_intrinsic_interp_var_at_centroid:
case nir_intrinsic_interp_var_at_sample: case nir_intrinsic_interp_var_at_sample:
case nir_intrinsic_interp_var_at_offset: case nir_intrinsic_interp_var_at_offset:
result = visit_interp(ctx->nctx, instr); result = visit_interp(ctx, instr);
break; break;
case nir_intrinsic_emit_vertex: case nir_intrinsic_emit_vertex:
ctx->abi->emit_vertex(ctx->abi, nir_intrinsic_stream_id(instr), ctx->outputs); ctx->abi->emit_vertex(ctx->abi, nir_intrinsic_stream_id(instr), ctx->outputs);
@@ -5426,7 +5430,7 @@ handle_fs_input_decl(struct nir_to_llvm_context *ctx,
else else
interp_type = INTERP_CENTER; interp_type = INTERP_CENTER;
interp = lookup_interp_param(ctx, variable->data.interpolation, interp_type); interp = lookup_interp_param(&ctx->abi, variable->data.interpolation, interp_type);
} else } else
interp = NULL; interp = NULL;
@@ -6870,6 +6874,8 @@ LLVMModuleRef ac_translate_nir_to_llvm(LLVMTargetMachineRef tm,
} }
} else if (shaders[i]->info.stage == MESA_SHADER_FRAGMENT) { } else if (shaders[i]->info.stage == MESA_SHADER_FRAGMENT) {
shader_info->fs.can_discard = shaders[i]->info.fs.uses_discard; shader_info->fs.can_discard = shaders[i]->info.fs.uses_discard;
ctx.abi.lookup_interp_param = lookup_interp_param;
ctx.abi.load_sample_position = load_sample_position;
} }
if (i) if (i)

View File

@@ -147,6 +147,13 @@ struct ac_shader_abi {
enum ac_descriptor_type desc_type, enum ac_descriptor_type desc_type,
bool image, bool write); bool image, bool write);
LLVMValueRef (*lookup_interp_param)(struct ac_shader_abi *abi,
enum glsl_interp_mode interp,
unsigned location);
LLVMValueRef (*load_sample_position)(struct ac_shader_abi *abi,
LLVMValueRef sample_id);
/* Whether to clamp the shadow reference value to [0,1]on VI. Radeonsi currently /* Whether to clamp the shadow reference value to [0,1]on VI. Radeonsi currently
* uses it due to promoting D16 to D32, but radv needs it off. */ * uses it due to promoting D16 to D32, but radv needs it off. */
bool clamp_shadow_reference; bool clamp_shadow_reference;

View File

@@ -6028,6 +6028,8 @@ static bool si_compile_tgsi_main(struct si_shader_context *ctx,
ctx->load_input = declare_input_fs; ctx->load_input = declare_input_fs;
ctx->abi.emit_outputs = si_llvm_return_fs_outputs; ctx->abi.emit_outputs = si_llvm_return_fs_outputs;
bld_base->emit_epilogue = si_tgsi_emit_epilogue; bld_base->emit_epilogue = si_tgsi_emit_epilogue;
ctx->abi.lookup_interp_param = si_nir_lookup_interp_param;
ctx->abi.load_sample_position = load_sample_position;
break; break;
case PIPE_SHADER_COMPUTE: case PIPE_SHADER_COMPUTE:
break; break;