nak/from_nir: Emit uniform instructions when !divergent

The really tricky case here is phis, which may have a uniform def even
though some of the srcs are non-uniform.  This happens because of the
restriction elsewhere that requires UGPRs and UPreds to only ever be
written in uniform control-flow.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29591>
This commit is contained in:
Faith Ekstrand 2024-05-29 15:21:00 -05:00 committed by Marge Bot
parent 3dfd92888a
commit d09d3f5246
3 changed files with 36 additions and 2 deletions

View file

@ -20,6 +20,7 @@ enum DebugFlags {
Serial, Serial,
Spill, Spill,
Annotate, Annotate,
NoUgpr,
} }
pub struct Debug { pub struct Debug {
@ -43,6 +44,7 @@ impl Debug {
"serial" => flags |= 1 << DebugFlags::Serial as u8, "serial" => flags |= 1 << DebugFlags::Serial as u8,
"spill" => flags |= 1 << DebugFlags::Spill as u8, "spill" => flags |= 1 << DebugFlags::Spill as u8,
"annotate" => flags |= 1 << DebugFlags::Annotate as u8, "annotate" => flags |= 1 << DebugFlags::Annotate as u8,
"nougpr" => flags |= 1 << DebugFlags::NoUgpr as u8,
unk => eprintln!("Unknown NAK_DEBUG flag \"{}\"", unk), unk => eprintln!("Unknown NAK_DEBUG flag \"{}\"", unk),
} }
} }
@ -68,6 +70,10 @@ pub trait GetDebugFlags {
fn annotate(&self) -> bool { fn annotate(&self) -> bool {
self.debug_flags() & (1 << DebugFlags::Annotate as u8) != 0 self.debug_flags() & (1 << DebugFlags::Annotate as u8) != 0
} }
fn no_ugpr(&self) -> bool {
self.debug_flags() & (1 << DebugFlags::NoUgpr as u8) != 0
}
} }
pub static DEBUG: OnceLock<Debug> = OnceLock::new(); pub static DEBUG: OnceLock<Debug> = OnceLock::new();

View file

@ -5,6 +5,7 @@
use crate::api::GetDebugFlags; use crate::api::GetDebugFlags;
use crate::api::DEBUG; use crate::api::DEBUG;
use crate::builder::*;
use crate::cfg::CFGBuilder; use crate::cfg::CFGBuilder;
use crate::ir::*; use crate::ir::*;
use crate::nir::*; use crate::nir::*;
@ -3122,10 +3123,23 @@ impl<'a> ShaderFromNir<'a> {
}); });
} }
let uniform = !nb.divergent
&& self.info.sm >= 75
&& !DEBUG.no_ugpr()
&& !np.def.divergent;
// This should be ensured by nak_nir_lower_cf()
if uniform {
for ps in np.iter_srcs() {
assert!(!ps.pred().divergent);
}
}
let mut b = UniformBuilder::new(&mut b, uniform);
let dst = alloc_ssa_for_nir(&mut b, np.def.as_def()); let dst = alloc_ssa_for_nir(&mut b, np.def.as_def());
for (i, dst) in dst.iter().enumerate() { for i in 0..dst.len() {
let phi_id = phi_map.get_phi_id(np, i.try_into().unwrap()); let phi_id = phi_map.get_phi_id(np, i.try_into().unwrap());
phi.dsts.push(phi_id, (*dst).into()); phi.dsts.push(phi_id, dst[i].into());
} }
self.set_ssa(np.def.as_def(), dst); self.set_ssa(np.def.as_def(), dst);
} }
@ -3148,6 +3162,12 @@ impl<'a> ShaderFromNir<'a> {
}); });
} }
let uniform = !nb.divergent
&& self.info.sm >= 75
&& !DEBUG.no_ugpr()
&& ni.def().is_some_and(|d| !d.divergent);
let mut b = UniformBuilder::new(&mut b, uniform);
match ni.type_ { match ni.type_ {
nir_instr_type_alu => { nir_instr_type_alu => {
self.parse_alu(&mut b, ni.as_alu().unwrap()) self.parse_alu(&mut b, ni.as_alu().unwrap())

View file

@ -467,6 +467,7 @@ pub trait NirInstr {
fn as_load_const(&self) -> Option<&nir_load_const_instr>; fn as_load_const(&self) -> Option<&nir_load_const_instr>;
fn as_undef(&self) -> Option<&nir_undef_instr>; fn as_undef(&self) -> Option<&nir_undef_instr>;
fn as_phi(&self) -> Option<&nir_phi_instr>; fn as_phi(&self) -> Option<&nir_phi_instr>;
fn def(&self) -> Option<&nir_def>;
} }
impl NirInstr for nir_instr { impl NirInstr for nir_instr {
@ -532,6 +533,13 @@ impl NirInstr for nir_instr {
None None
} }
} }
fn def(&self) -> Option<&nir_def> {
unsafe {
let def = nir_instr_def(self as *const _ as *mut _);
NonNull::new(def).map(|d| d.as_ref())
}
}
} }
pub trait NirBlock { pub trait NirBlock {