nak: Add tests for OpISetP

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30381>
This commit is contained in:
Faith Ekstrand
2024-07-24 21:27:26 -05:00
committed by Marge Bot
parent 6056bc4afa
commit bfcb9995da
2 changed files with 123 additions and 1 deletions

View File

@@ -566,6 +566,61 @@ fn test_op_iadd3x() {
}
}
#[test]
fn test_op_isetp() {
let set_ops = [PredSetOp::And, PredSetOp::Or, PredSetOp::Xor];
let cmp_ops = [
IntCmpOp::Eq,
IntCmpOp::Ne,
IntCmpOp::Lt,
IntCmpOp::Le,
IntCmpOp::Gt,
IntCmpOp::Ge,
];
let cmp_types = [IntCmpType::U32, IntCmpType::I32];
for mut i in 0..(set_ops.len() * cmp_ops.len() * cmp_types.len() * 2) {
let set_op = set_ops[i % set_ops.len()];
i /= set_ops.len();
let cmp_op = cmp_ops[i % cmp_ops.len()];
i /= cmp_ops.len();
let cmp_type = cmp_types[i % cmp_types.len()];
i /= cmp_types.len();
let ex = i != 0;
let op = OpISetP {
dst: Dst::None,
set_op,
cmp_op,
cmp_type,
ex,
srcs: [0.into(), 0.into()],
accum: 0.into(),
low_cmp: 0.into(),
};
let src0_idx = op.src_idx(&op.srcs[0]);
let mut a = Acorn::new();
let mut src0 = 0_u32;
test_foldable_op_with(op, &mut |i| {
let x = a.get_u32();
if i == src0_idx {
src0 = x;
}
// Make src0 and src1
if i == src0_idx + 1 && a.get_bool() {
src0
} else {
x
}
});
}
}
#[test]
fn test_op_shf() {
let sm = &RunSingleton::get().sm;

View File

@@ -3541,7 +3541,7 @@ impl DisplayOp for OpIMnMx {
impl_display_for_op!(OpIMnMx);
#[repr(C)]
#[derive(SrcsAsSlice, DstsAsSlice)]
#[derive(Clone, SrcsAsSlice, DstsAsSlice)]
pub struct OpISetP {
#[dst_type(Pred)]
pub dst: Dst,
@@ -3561,6 +3561,73 @@ pub struct OpISetP {
pub low_cmp: Src,
}
impl Foldable for OpISetP {
fn fold(&self, sm: &dyn ShaderModel, f: &mut OpFoldData<'_>) {
let x = f.get_u32_src(self, &self.srcs[0]);
let y = f.get_u32_src(self, &self.srcs[1]);
let accum = f.get_pred_src(self, &self.accum);
let low_cmp = f.get_pred_src(self, &self.low_cmp);
let cmp = if self.cmp_type.is_signed() {
let x = x as i32;
let y = y as i32;
match &self.cmp_op {
IntCmpOp::Eq => x == y,
IntCmpOp::Ne => x != y,
IntCmpOp::Lt => x < y,
IntCmpOp::Le => x <= y,
IntCmpOp::Gt => x > y,
IntCmpOp::Ge => x >= y,
}
} else {
match &self.cmp_op {
IntCmpOp::Eq => x == y,
IntCmpOp::Ne => x != y,
IntCmpOp::Lt => x < y,
IntCmpOp::Le => x <= y,
IntCmpOp::Gt => x > y,
IntCmpOp::Ge => x >= y,
}
};
let dst = if sm.sm() >= 70 {
let cmp = if self.ex && x == y { low_cmp } else { cmp };
match &self.set_op {
PredSetOp::And => cmp & accum,
PredSetOp::Or => cmp | accum,
PredSetOp::Xor => cmp ^ accum,
}
} else {
if self.ex && x == y {
match self.cmp_op {
IntCmpOp::Eq | IntCmpOp::Gt | IntCmpOp::Ge => {
match &self.set_op {
PredSetOp::And => false,
PredSetOp::Or => accum,
PredSetOp::Xor => accum,
}
}
IntCmpOp::Ne | IntCmpOp::Lt | IntCmpOp::Le => {
match &self.set_op {
PredSetOp::And => accum,
PredSetOp::Or => true,
PredSetOp::Xor => !accum,
}
}
}
} else {
match &self.set_op {
PredSetOp::And => cmp & accum,
PredSetOp::Or => cmp | accum,
PredSetOp::Xor => cmp ^ accum,
}
}
};
f.set_pred_dst(self, &self.dst, dst);
}
}
impl DisplayOp for OpISetP {
fn fmt_op(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "isetp{}{}", self.cmp_op, self.cmp_type)?;