nak: Implement bitfield_extract with OpSgxt

on sm70+ where we don't have a native bfe instruction. This
implementation is fewer instructions than the nir lowering.

This also implements the bfe semantics that vkd3d-proton wants. d3d12
wants specific behavior for out-of-bounds ibfe like
bitfieldExtract(-1, 15, 20) while spirv considers this undefined
behavior. Tested with VKD3D_TEST_FILTER=test_shader_instructions

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/13795
Reviewed-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37592>
This commit is contained in:
Mel Henning
2025-09-25 19:59:33 -04:00
committed by Marge Bot
parent c8116679c3
commit d32e6f2842
2 changed files with 27 additions and 16 deletions
+1 -1
View File
@@ -123,7 +123,7 @@ fn nir_options(dev: &nv_device_info) -> nir_shader_compiler_options {
op.lower_flrp32 = true;
op.lower_flrp64 = true;
op.lower_fsqrt = dev.sm < 52;
op.lower_bitfield_extract = dev.sm >= 70;
op.lower_bitfield_extract = false;
op.lower_bitfield_extract8 = true;
op.lower_bitfield_extract16 = true;
op.lower_bitfield_insert = true;
+26 -15
View File
@@ -752,22 +752,33 @@ impl<'a> ShaderFromNir<'a> {
}
nir_op_bitfield_reverse => b.brev(srcs(0)).into(),
nir_op_ibitfield_extract | nir_op_ubitfield_extract => {
let range = b.alloc_ssa(RegFile::GPR);
b.push_op(OpPrmt {
dst: range.into(),
srcs: [srcs(1), srcs(2)],
sel: 0x0040.into(),
mode: PrmtMode::Index,
});
let dst = b.alloc_ssa(RegFile::GPR);
b.push_op(OpBfe {
dst: dst.into(),
base: srcs(0),
signed: !matches!(alu.op, nir_op_ubitfield_extract),
range: range.into(),
reverse: false,
});
let signed = !matches!(alu.op, nir_op_ubitfield_extract);
if self.sm.sm() >= 70 {
let shifted = b.shr(srcs(0), srcs(1), signed);
b.push_op(OpSgxt {
dst: dst.into(),
a: shifted.into(),
bits: srcs(2),
signed,
});
} else {
let range = b.alloc_ssa(RegFile::GPR);
b.push_op(OpPrmt {
dst: range.into(),
srcs: [srcs(1), srcs(2)],
sel: 0x0040.into(),
mode: PrmtMode::Index,
});
b.push_op(OpBfe {
dst: dst.into(),
base: srcs(0),
signed,
range: range.into(),
reverse: false,
});
};
dst.into()
}
nir_op_extract_u8 | nir_op_extract_i8 | nir_op_extract_u16