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

View file

@ -5,6 +5,7 @@
use crate::api::GetDebugFlags;
use crate::api::DEBUG;
use crate::builder::*;
use crate::cfg::CFGBuilder;
use crate::ir::*;
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());
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());
phi.dsts.push(phi_id, (*dst).into());
phi.dsts.push(phi_id, dst[i].into());
}
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_ {
nir_instr_type_alu => {
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_undef(&self) -> Option<&nir_undef_instr>;
fn as_phi(&self) -> Option<&nir_phi_instr>;
fn def(&self) -> Option<&nir_def>;
}
impl NirInstr for nir_instr {
@ -532,6 +533,13 @@ impl NirInstr for nir_instr {
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 {