intel/compiler: Do interpolateAtOffset coordinate scaling in NIR
In our source languages, interpolateAtOffset() takes a floating point offset in the range [-0.5, +0.5]. However, the hardware takes integer valued offsets in the range [-8, 7], in units of 1/16th of a pixel. So, we need to multiply and clamp the coordinates. We were doing this in the FS backend, but with the advent of IBC, I'd like to avoid doing it twice. This patch instead moves the lowering to NIR so we can reuse it across both backends. v2: Use nir_shader_instructions_pass (suggested by Eric Anholt). Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com> Reviewed-by: Matt Turner <mattst88@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6193>
This commit is contained in:

committed by
Marge Bot

parent
0d3b61dd7e
commit
97ebb896af
@@ -364,6 +364,45 @@ brw_nir_lower_tes_inputs(nir_shader *nir, const struct brw_vue_map *vue_map)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert interpolateAtOffset() offsets from [-0.5, +0.5] floating point
|
||||
* offsets to integer [-8, +7] offsets (in units of 1/16th of a pixel).
|
||||
*
|
||||
* We clamp to +7/16 on the upper end of the range, since +0.5 isn't
|
||||
* representable in a S0.4 value; a naive conversion would give us -8/16,
|
||||
* which is the opposite of what was intended.
|
||||
*
|
||||
* This is allowed by GL_ARB_gpu_shader5's quantization rules:
|
||||
*
|
||||
* "Not all values of <offset> may be supported; x and y offsets may
|
||||
* be rounded to fixed-point values with the number of fraction bits
|
||||
* given by the implementation-dependent constant
|
||||
* FRAGMENT_INTERPOLATION_OFFSET_BITS."
|
||||
*/
|
||||
static bool
|
||||
lower_barycentric_at_offset(nir_builder *b, nir_instr *instr, void *data)
|
||||
{
|
||||
if (instr->type != nir_instr_type_intrinsic)
|
||||
return false;
|
||||
|
||||
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
|
||||
|
||||
if (intrin->intrinsic != nir_intrinsic_load_barycentric_at_offset)
|
||||
return false;
|
||||
|
||||
b->cursor = nir_before_instr(instr);
|
||||
|
||||
assert(intrin->src[0].ssa);
|
||||
nir_ssa_def *offset =
|
||||
nir_imin(b, nir_imm_int(b, 7),
|
||||
nir_f2i32(b, nir_fmul(b, nir_imm_float(b, 16),
|
||||
intrin->src[0].ssa)));
|
||||
|
||||
nir_instr_rewrite_src(instr, &intrin->src[0], nir_src_for_ssa(offset));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
brw_nir_lower_fs_inputs(nir_shader *nir,
|
||||
const struct gen_device_info *devinfo,
|
||||
@@ -404,6 +443,11 @@ brw_nir_lower_fs_inputs(nir_shader *nir,
|
||||
if (devinfo->gen >= 11)
|
||||
nir_lower_interpolation(nir, ~0);
|
||||
|
||||
nir_shader_instructions_pass(nir, lower_barycentric_at_offset,
|
||||
nir_metadata_block_index |
|
||||
nir_metadata_dominance,
|
||||
NULL);
|
||||
|
||||
/* This pass needs actual constants */
|
||||
nir_opt_constant_folding(nir);
|
||||
|
||||
|
Reference in New Issue
Block a user