mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-09 04:38:03 +02:00
nak: Implement input interpolation
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24998>
This commit is contained in:
parent
6595abc1e0
commit
8c358ce105
5 changed files with 180 additions and 1 deletions
|
|
@ -19,6 +19,8 @@ mod nir;
|
|||
mod union_find;
|
||||
mod util;
|
||||
|
||||
use crate::nir::NirShader;
|
||||
|
||||
use bitview::*;
|
||||
use nak_bindings::*;
|
||||
use nak_from_nir::*;
|
||||
|
|
@ -276,6 +278,32 @@ fn encode_hdr_for_nir(nir: &nir_shader, tls_size: u32) -> [u32; 32] {
|
|||
imap_sv.set_bit(31, true); //has_frag_coord);
|
||||
|
||||
/* [192, 447]: ImapGenericVector[32] */
|
||||
/* TODO: Non-perspective */
|
||||
let mut imap_g = hdr_view.subset_mut(192..447);
|
||||
|
||||
let nir_ir = BitView::new(&nir.info.inputs_read);
|
||||
let input0: usize = VARYING_SLOT_VAR0.try_into().unwrap();
|
||||
for var in nir.iter_variables() {
|
||||
if var.data.mode() != nir_var_shader_in {
|
||||
continue;
|
||||
}
|
||||
let loc_u32 = u32::try_from(var.data.location).unwrap();
|
||||
let slot =
|
||||
(loc_u32 - VARYING_SLOT_VAR0) * 4 + var.data.location_frac();
|
||||
let num_slots = unsafe { glsl_get_component_slots(var.type_) };
|
||||
let mode: u8 = match var.data.interpolation() {
|
||||
INTERP_MODE_NONE | INTERP_MODE_SMOOTH => 2, /* Perspective */
|
||||
INTERP_MODE_FLAT => 1, /* Constant */
|
||||
INTERP_MODE_NOPERSPECTIVE => 3, /* ScreenLinear */
|
||||
INTERP_MODE_EXPLICIT => 0, /* Unused */
|
||||
_ => panic!("Unsupported INTERP_MODE"),
|
||||
};
|
||||
for s in slot..(slot + num_slots) {
|
||||
let s = usize::try_from(s).unwrap();
|
||||
imap_g.set_field((s * 2)..(s * 2 + 2), mode);
|
||||
}
|
||||
}
|
||||
|
||||
/* [448, 463]: ImapColor */
|
||||
/* [464, 479]: ImapSystemValuesC */
|
||||
/* [480, 559]: ImapFixedFncTexture[10] */
|
||||
|
|
|
|||
|
|
@ -766,6 +766,37 @@ impl SM75Instr {
|
|||
assert!(!op.access.out_load);
|
||||
}
|
||||
|
||||
fn encode_ipa(&mut self, op: &OpIpa) {
|
||||
self.set_opcode(0x326);
|
||||
|
||||
self.set_dst(op.dst);
|
||||
|
||||
assert!(op.addr % 4 == 0);
|
||||
self.set_field(64..72, op.addr >> 2);
|
||||
|
||||
self.set_field(
|
||||
76..78,
|
||||
match op.freq {
|
||||
InterpFreq::Pass => 0_u8,
|
||||
InterpFreq::Constant => 1_u8,
|
||||
InterpFreq::State => 2_u8,
|
||||
},
|
||||
);
|
||||
self.set_field(
|
||||
78..80,
|
||||
match op.loc {
|
||||
InterpLoc::Default => 0_u8,
|
||||
InterpLoc::Centroid => 1_u8,
|
||||
InterpLoc::Offset => 2_u8,
|
||||
},
|
||||
);
|
||||
|
||||
self.set_reg_src(32..40, op.offset);
|
||||
|
||||
/* TODO: What is this for? */
|
||||
self.set_pred_dst(81..84, Dst::None);
|
||||
}
|
||||
|
||||
fn encode_bra(
|
||||
&mut self,
|
||||
op: &OpBra,
|
||||
|
|
@ -837,6 +868,7 @@ impl SM75Instr {
|
|||
Op::St(op) => si.encode_st(&op),
|
||||
Op::ALd(op) => si.encode_ald(&op),
|
||||
Op::ASt(op) => si.encode_ast(&op),
|
||||
Op::Ipa(op) => si.encode_ipa(&op),
|
||||
Op::Bra(op) => si.encode_bra(&op, ip, block_offsets),
|
||||
Op::Exit(op) => si.encode_exit(&op),
|
||||
Op::S2R(op) => si.encode_s2r(&op),
|
||||
|
|
|
|||
|
|
@ -484,6 +484,9 @@ impl<'a> ShaderFromNir<'a> {
|
|||
fn parse_intrinsic(&mut self, intrin: &nir_intrinsic_instr) {
|
||||
let srcs = intrin.srcs_as_slice();
|
||||
match intrin.intrinsic {
|
||||
nir_intrinsic_load_barycentric_centroid => (),
|
||||
nir_intrinsic_load_barycentric_pixel => (),
|
||||
nir_intrinsic_load_barycentric_sample => (),
|
||||
nir_intrinsic_load_global => {
|
||||
let size_B =
|
||||
(intrin.def.bit_size() / 8) * intrin.def.num_components();
|
||||
|
|
@ -505,6 +508,32 @@ impl<'a> ShaderFromNir<'a> {
|
|||
let dst = self.get_dst(&intrin.def);
|
||||
self.instrs.push(Instr::new_ald(dst, addr, vtx, offset));
|
||||
}
|
||||
nir_intrinsic_load_interpolated_input => {
|
||||
let bary =
|
||||
srcs[0].as_def().parent_instr().as_intrinsic().unwrap();
|
||||
let addr = u16::try_from(intrin.base()).unwrap()
|
||||
+ u16::try_from(srcs[1].as_uint().unwrap()).unwrap();
|
||||
let freq = InterpFreq::Pass;
|
||||
let loc = match bary.intrinsic {
|
||||
nir_intrinsic_load_barycentric_pixel => InterpLoc::Default,
|
||||
_ => panic!("Unsupported interp mode"),
|
||||
};
|
||||
let dst = self.get_dst(&intrin.def);
|
||||
|
||||
let mut comps = Vec::new();
|
||||
for c in 0..intrin.num_components {
|
||||
let tmp = self.alloc_ssa(RegFile::GPR, 1);
|
||||
self.instrs.push(Instr::new(Op::Ipa(OpIpa {
|
||||
dst: tmp.into(),
|
||||
addr: addr + 4 * u16::try_from(c).unwrap(),
|
||||
freq: freq,
|
||||
loc: loc,
|
||||
offset: SrcRef::Zero.into(),
|
||||
})));
|
||||
comps.push(tmp.into());
|
||||
}
|
||||
self.instrs.push(Instr::new_vec(dst, &comps));
|
||||
}
|
||||
nir_intrinsic_load_per_vertex_input => {
|
||||
let addr = u16::try_from(intrin.base()).unwrap();
|
||||
let vtx = self.get_src(&srcs[0]);
|
||||
|
|
|
|||
|
|
@ -1011,6 +1011,20 @@ impl fmt::Display for MemAccess {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
pub enum InterpFreq {
|
||||
Pass,
|
||||
Constant,
|
||||
State,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
pub enum InterpLoc {
|
||||
Default,
|
||||
Centroid,
|
||||
Offset,
|
||||
}
|
||||
|
||||
pub struct AttrAccess {
|
||||
pub addr: u16,
|
||||
pub comps: u8,
|
||||
|
|
@ -1427,6 +1441,38 @@ impl fmt::Display for OpASt {
|
|||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(SrcsAsSlice, DstsAsSlice)]
|
||||
pub struct OpIpa {
|
||||
pub dst: Dst,
|
||||
pub addr: u16,
|
||||
pub freq: InterpFreq,
|
||||
pub loc: InterpLoc,
|
||||
pub offset: Src,
|
||||
}
|
||||
|
||||
impl fmt::Display for OpIpa {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "IPA")?;
|
||||
match self.freq {
|
||||
InterpFreq::Pass => (),
|
||||
InterpFreq::Constant => write!(f, ".CONSTANT")?,
|
||||
InterpFreq::State => write!(f, ".STATE")?,
|
||||
}
|
||||
match self.loc {
|
||||
InterpLoc::Default => (),
|
||||
InterpLoc::Centroid => write!(f, ".CENTROID")?,
|
||||
InterpLoc::Offset => write!(f, ".OFFSET")?,
|
||||
}
|
||||
|
||||
write!(f, " {} a[{:#x}]", self.dst, self.addr)?;
|
||||
if !self.offset.is_zero() {
|
||||
write!(f, " {}", self.offset)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(SrcsAsSlice, DstsAsSlice)]
|
||||
pub struct OpBra {
|
||||
|
|
@ -1763,6 +1809,7 @@ pub enum Op {
|
|||
St(OpSt),
|
||||
ALd(OpALd),
|
||||
ASt(OpASt),
|
||||
Ipa(OpIpa),
|
||||
Bra(OpBra),
|
||||
Exit(OpExit),
|
||||
S2R(OpS2R),
|
||||
|
|
@ -2218,6 +2265,7 @@ impl Instr {
|
|||
Op::S2R(_) => None,
|
||||
Op::ALd(_) => None,
|
||||
Op::ASt(_) => Some(15),
|
||||
Op::Ipa(_) => None,
|
||||
Op::Ld(_) => None,
|
||||
Op::St(_) => None,
|
||||
Op::Bra(_) | Op::Exit(_) => Some(15),
|
||||
|
|
|
|||
|
|
@ -312,6 +312,48 @@ vec_size_4(const struct glsl_type *type, bool bindless)
|
|||
return 4;
|
||||
}
|
||||
|
||||
static bool
|
||||
nak_nir_lower_fs_inputs(nir_shader *nir)
|
||||
{
|
||||
bool progress = false;
|
||||
|
||||
OPT(nir, nak_nir_lower_varyings, nir_var_shader_in);
|
||||
|
||||
if (!progress)
|
||||
return false;
|
||||
|
||||
nir_function_impl *impl = nir_shader_get_entrypoint(nir);
|
||||
|
||||
const uint16_t w_addr =
|
||||
nak_sysval_attr_addr(SYSTEM_VALUE_FRAG_COORD) + 12;
|
||||
|
||||
nir_builder b = nir_builder_create(impl);
|
||||
|
||||
nir_foreach_block(block, impl) {
|
||||
nir_foreach_instr_safe(instr, block) {
|
||||
if (instr->type != nir_instr_type_intrinsic)
|
||||
continue;
|
||||
|
||||
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
|
||||
if (intrin->intrinsic != nir_intrinsic_load_interpolated_input)
|
||||
continue;
|
||||
|
||||
b.cursor = nir_after_instr(&intrin->instr);
|
||||
|
||||
nir_def *w =
|
||||
nir_load_interpolated_input(&b, 1, 32, intrin->src[0].ssa,
|
||||
nir_imm_int(&b, 0), .base = w_addr,
|
||||
.dest_type = nir_type_float32);
|
||||
|
||||
/* Interpolated inputs need to be divided by .w */
|
||||
nir_def *res = nir_fdiv(&b, &intrin->def, w);
|
||||
nir_def_rewrite_uses_after(&intrin->def, res, res->parent_instr);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
nak_nir_lower_fs_outputs(nir_shader *nir)
|
||||
{
|
||||
|
|
@ -502,7 +544,7 @@ nak_postprocess_nir(nir_shader *nir, const struct nak_compiler *nak)
|
|||
break;
|
||||
|
||||
case MESA_SHADER_FRAGMENT:
|
||||
OPT(nir, nak_nir_lower_varyings, nir_var_shader_in);
|
||||
OPT(nir, nak_nir_lower_fs_inputs);
|
||||
OPT(nir, nak_nir_lower_fs_outputs);
|
||||
break;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue