diff --git a/src/nouveau/compiler/nak_from_nir.rs b/src/nouveau/compiler/nak_from_nir.rs index 436ed5c156c..18df8cd5102 100644 --- a/src/nouveau/compiler/nak_from_nir.rs +++ b/src/nouveau/compiler/nak_from_nir.rs @@ -51,6 +51,8 @@ fn init_info_from_nir(nir: &nir_shader, sm: u8) -> ShaderInfo { }; ShaderStageInfo::Geometry(GeometryShaderInfo { + // TODO: Should be set if VK_NV_geometry_shader_passthrough is in use. + passthrough_enable: false, stream_out_mask: info_gs.active_stream_mask(), threads_per_input_primitive: info_gs.invocations, output_topology: output_topology, @@ -75,19 +77,25 @@ fn init_info_from_nir(nir: &nir_shader, sm: u8) -> ShaderInfo { ab: 1 << 31, c: 0, }, + sysvals_in_d: [PixelImap::Unused; 8], attr_in: [PixelImap::Unused; 128], + barycentric_attr_in: [0; 4], reads_sample_mask: false, uses_kill: false, writes_color: 0, writes_sample_mask: false, writes_depth: false, + // TODO: Should be set if interlocks are in use. (VK_EXT_fragment_shader_interlock) + does_interlock: false, }), MESA_SHADER_VERTEX | MESA_SHADER_GEOMETRY | MESA_SHADER_TESS_CTRL | MESA_SHADER_TESS_EVAL => ShaderIoInfo::Vtg(VtgIoInfo { sysvals_in: SysValInfo::default(), + sysvals_in_d: 0, sysvals_out: SysValInfo::default(), + sysvals_out_d: 0, attr_in: [0; 4], attr_out: [0; 4], diff --git a/src/nouveau/compiler/nak_ir.rs b/src/nouveau/compiler/nak_ir.rs index 8fba9ef3597..6af4eb1a05f 100644 --- a/src/nouveau/compiler/nak_ir.rs +++ b/src/nouveau/compiler/nak_ir.rs @@ -4930,6 +4930,7 @@ pub struct ComputeShaderInfo { #[derive(Debug)] pub struct GeometryShaderInfo { + pub passthrough_enable: bool, pub stream_out_mask: u8, pub threads_per_input_primitive: u8, pub output_topology: OutputTopology, @@ -4939,6 +4940,7 @@ pub struct GeometryShaderInfo { impl Default for GeometryShaderInfo { fn default() -> Self { Self { + passthrough_enable: false, stream_out_mask: 0, threads_per_input_primitive: 0, output_topology: OutputTopology::LineStrip, @@ -4972,7 +4974,9 @@ pub struct SysValInfo { #[derive(Debug)] pub struct VtgIoInfo { pub sysvals_in: SysValInfo, + pub sysvals_in_d: u8, pub sysvals_out: SysValInfo, + pub sysvals_out_d: u8, pub attr_in: [u32; 4], pub attr_out: [u32; 4], pub store_req_start: u8, @@ -4987,6 +4991,12 @@ impl VtgIoInfo { &mut self.sysvals_in }; + let sysvals_d = if written { + &mut self.sysvals_out_d + } else { + &mut self.sysvals_in_d + }; + let mut attr = BitMutView::new(if written { &mut self.attr_out } else { @@ -5005,6 +5015,8 @@ impl VtgIoInfo { panic!("FF color I/O not supported"); } else if addr < 0x300 { sysvals.c |= 1 << ((addr - 0x2c0) / 4); + } else if addr >= 0x3a0 && addr < 0x3c0 { + *sysvals_d |= 1 << ((addr - 0x3a0) / 4); } } } @@ -5028,13 +5040,16 @@ impl VtgIoInfo { #[derive(Debug)] pub struct FragmentIoInfo { pub sysvals_in: SysValInfo, + pub sysvals_in_d: [PixelImap; 8], pub attr_in: [PixelImap; 128], + pub barycentric_attr_in: [u32; 4], pub reads_sample_mask: bool, pub uses_kill: bool, pub writes_color: u32, pub writes_sample_mask: bool, pub writes_depth: bool, + pub does_interlock: bool, } impl FragmentIoInfo { @@ -5048,8 +5063,20 @@ impl FragmentIoInfo { panic!("FF color I/O not supported"); } else if addr < 0x300 { self.sysvals_in.c |= 1 << ((addr - 0x2c0) / 4); + } else if addr >= 0x3a0 && addr < 0x3c0 { + let attr_idx = (addr - 0x3a0) as usize / 4; + self.sysvals_in_d[attr_idx] = interp; } } + + pub fn mark_barycentric_attr_in(&mut self, addr: u16) { + assert!(addr >= 0x80 && addr < 0x280); + + let mut attr = BitMutView::new(&mut self.barycentric_attr_in); + + let attr_idx = (addr - 0x080) as usize / 4; + attr.set_bit(attr_idx, true); + } } #[derive(Debug)] diff --git a/src/nouveau/compiler/nak_sph.rs b/src/nouveau/compiler/nak_sph.rs index 01ad101a6ae..1b8a7f8754f 100644 --- a/src/nouveau/compiler/nak_sph.rs +++ b/src/nouveau/compiler/nak_sph.rs @@ -172,6 +172,12 @@ impl ShaderProgramHeader { } } + #[inline] + fn imap_system_values_d_vtg(&mut self) -> SubSPHView<'_> { + assert!(self.shader_type != ShaderType::Fragment); + BitMutView::new_subset(&mut self.data, 392..400) + } + #[inline] fn omap_system_values_ab(&mut self) -> SubSPHView<'_> { assert!(self.shader_type != ShaderType::Fragment); @@ -191,6 +197,12 @@ impl ShaderProgramHeader { BitMutView::new_subset(&mut self.data, 576..592) } + #[inline] + fn imap_system_values_d_ps(&mut self) -> SubSPHView<'_> { + assert!(self.shader_type == ShaderType::Fragment); + BitMutView::new_subset(&mut self.data, 560..576) + } + #[inline] fn omap_target(&mut self) -> SubSPHView<'_> { assert!(self.shader_type == ShaderType::Fragment); @@ -198,6 +210,12 @@ impl ShaderProgramHeader { BitMutView::new_subset(&mut self.data, 576..608) } + #[inline] + fn omap_system_values_d_vtg(&mut self) -> SubSPHView<'_> { + assert!(self.shader_type != ShaderType::Fragment); + BitMutView::new_subset(&mut self.data, 632..640) + } + #[inline] fn set_sph_type(&mut self, sph_type: u8, sph_version: u8) { let mut common_word0 = self.common_word0(); @@ -240,6 +258,12 @@ impl ShaderProgramHeader { self.common_word0().set_field(17..21, sass_version); } + #[inline] + pub fn set_gs_passthrough_enable(&mut self, gs_passthrough_enable: bool) { + assert!(self.shader_type == ShaderType::Geometry); + self.common_word0().set_bit(24, gs_passthrough_enable); + } + #[inline] pub fn set_does_load_or_store(&mut self, does_load_or_store: bool) { self.common_word0().set_bit(26, does_load_or_store); @@ -349,6 +373,11 @@ impl ShaderProgramHeader { self.imap_system_values_c().set_field(0..16, val); } + pub fn set_imap_system_values_d_vtg(&mut self, val: u8) { + assert!(self.shader_type != ShaderType::Fragment); + self.imap_system_values_d_vtg().set_field(0..8, val); + } + #[inline] pub fn set_imap_vector_ps(&mut self, index: usize, value: PixelImap) { assert!(index < 128); @@ -358,6 +387,19 @@ impl ShaderProgramHeader { .set_field(index * 2..(index + 1) * 2, u8::from(value)); } + #[inline] + pub fn set_imap_system_values_d_ps( + &mut self, + index: usize, + value: PixelImap, + ) { + assert!(index < 8); + assert!(self.shader_type == ShaderType::Fragment); + + self.imap_system_values_d_ps() + .set_field(index * 2..(index + 1) * 2, u8::from(value)); + } + #[inline] pub fn set_imap_vector_vtg(&mut self, index: usize, value: u32) { assert!(index < 4); @@ -377,6 +419,11 @@ impl ShaderProgramHeader { self.omap_system_values_c().set_field(0..16, val); } + pub fn set_omap_system_values_d_vtg(&mut self, val: u8) { + assert!(self.shader_type != ShaderType::Fragment); + self.omap_system_values_d_vtg().set_field(0..8, val); + } + #[inline] pub fn set_omap_vector(&mut self, index: usize, value: u32) { assert!(index < 4); @@ -401,6 +448,35 @@ impl ShaderProgramHeader { assert!(self.shader_type == ShaderType::Fragment); self.set_bit(609, depth); } + + #[inline] + pub fn set_does_interlock(&mut self, does_interlock: bool) { + assert!(self.shader_type == ShaderType::Fragment); + self.set_bit(610, does_interlock); + } + + // TODO: This seems always set on fragment shaders, figure out what this is for. + #[inline] + pub fn set_unknown_bit611(&mut self, value: bool) { + assert!(self.shader_type == ShaderType::Fragment); + self.set_bit(611, value); + } + + #[inline] + fn pervertex_imap_vector_ps(&mut self) -> SubSPHView<'_> { + assert!(self.shader_type == ShaderType::Fragment); + + BitMutView::new_subset(&mut self.data, 672..800) + } + + #[inline] + pub fn set_pervertex_imap_vector(&mut self, index: usize, value: u32) { + assert!(index < 4); + assert!(self.shader_type == ShaderType::Fragment); + + self.pervertex_imap_vector_ps() + .set_field(index * 32..(index + 1) * 32, value); + } } pub fn encode_header( @@ -428,6 +504,7 @@ pub fn encode_header( ShaderIoInfo::Vtg(io) => { sph.set_imap_system_values_ab(io.sysvals_in.ab); sph.set_imap_system_values_c(io.sysvals_in.c); + sph.set_imap_system_values_d_vtg(io.sysvals_in_d); for (index, value) in io.attr_in.iter().enumerate() { sph.set_imap_vector_vtg(index, *value); @@ -442,11 +519,16 @@ pub fn encode_header( sph.set_omap_system_values_ab(io.sysvals_out.ab); sph.set_omap_system_values_c(io.sysvals_out.c); + sph.set_omap_system_values_d_vtg(io.sysvals_out_d); } ShaderIoInfo::Fragment(io) => { sph.set_imap_system_values_ab(io.sysvals_in.ab); sph.set_imap_system_values_c(io.sysvals_in.c); + for (index, imap) in io.sysvals_in_d.iter().enumerate() { + sph.set_imap_system_values_d_ps(index, *imap); + } + for (index, imap) in io.attr_in.iter().enumerate() { sph.set_imap_vector_ps(index, *imap); } @@ -458,12 +540,18 @@ pub fn encode_header( sph.set_omap_sample_mask(io.writes_sample_mask); sph.set_omap_depth(io.writes_depth); sph.set_omap_targets(io.writes_color); + sph.set_does_interlock(io.does_interlock); + + for (index, value) in io.barycentric_attr_in.iter().enumerate() { + sph.set_pervertex_imap_vector(index, *value); + } } _ => {} } match &shader_info.stage { ShaderStageInfo::Geometry(stage) => { + sph.set_gs_passthrough_enable(stage.passthrough_enable); sph.set_stream_out_mask(stage.stream_out_mask); sph.set_threads_per_input_primitive( stage.threads_per_input_primitive,