From d32e6f2842fe4a3a96f52048383514f6f2f38c17 Mon Sep 17 00:00:00 2001 From: Mel Henning Date: Thu, 25 Sep 2025 19:59:33 -0400 Subject: [PATCH] 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 Part-of: --- src/nouveau/compiler/nak/api.rs | 2 +- src/nouveau/compiler/nak/from_nir.rs | 41 ++++++++++++++++++---------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/nouveau/compiler/nak/api.rs b/src/nouveau/compiler/nak/api.rs index 237d9b111b8..74e2f9cbe17 100644 --- a/src/nouveau/compiler/nak/api.rs +++ b/src/nouveau/compiler/nak/api.rs @@ -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; diff --git a/src/nouveau/compiler/nak/from_nir.rs b/src/nouveau/compiler/nak/from_nir.rs index a07cca69fc9..660d0864b9b 100644 --- a/src/nouveau/compiler/nak/from_nir.rs +++ b/src/nouveau/compiler/nak/from_nir.rs @@ -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