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:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user