nak: Restructure ShaderInfo
Signed-off-by: Mary Guillemard <mary.guillemard@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24998>
This commit is contained in:
committed by
Marge Bot
parent
267a4f07d0
commit
145213fd2c
@@ -31,6 +31,7 @@ use crate::nak_ir::ShaderStageInfo;
|
||||
use bitview::*;
|
||||
use nak_bindings::*;
|
||||
use nak_from_nir::*;
|
||||
use nak_ir::ShaderIoInfo;
|
||||
use std::env;
|
||||
use std::ffi::CStr;
|
||||
use std::os::raw::c_void;
|
||||
@@ -294,7 +295,12 @@ pub extern "C" fn nak_compile_shader(
|
||||
},
|
||||
}
|
||||
}
|
||||
ShaderStageInfo::Fragment(fs_info) => {
|
||||
ShaderStageInfo::Fragment => {
|
||||
let fs_info = match &s.info.io {
|
||||
ShaderIoInfo::Fragment(io) => io,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let nir_fs_info = unsafe { &nir.info.__bindgen_anon_1.fs };
|
||||
nak_shader_info__bindgen_ty_1 {
|
||||
fs: nak_shader_info__bindgen_ty_1__bindgen_ty_2 {
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#![allow(non_upper_case_globals)]
|
||||
#![allow(unstable_name_collisions)]
|
||||
|
||||
use crate::bitset::BitSet;
|
||||
use crate::bitview::{BitMutView, BitView, SetField};
|
||||
use crate::nak_cfg::CFGBuilder;
|
||||
use crate::nak_ir::*;
|
||||
use crate::nak_sph::{OutputTopology, PixelImap};
|
||||
@@ -18,7 +20,7 @@ use std::cmp::min;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
fn init_info_from_nir(nir: &nir_shader, sm: u8) -> ShaderInfo {
|
||||
let mut res = ShaderInfo {
|
||||
ShaderInfo {
|
||||
sm: sm,
|
||||
num_gprs: 0,
|
||||
tls_size: nir.scratch_size,
|
||||
@@ -38,9 +40,7 @@ fn init_info_from_nir(nir: &nir_shader, sm: u8) -> ShaderInfo {
|
||||
})
|
||||
}
|
||||
MESA_SHADER_VERTEX => ShaderStageInfo::Vertex,
|
||||
MESA_SHADER_FRAGMENT => {
|
||||
ShaderStageInfo::Fragment(Default::default())
|
||||
}
|
||||
MESA_SHADER_FRAGMENT => ShaderStageInfo::Fragment,
|
||||
MESA_SHADER_GEOMETRY => {
|
||||
let info_gs = unsafe { &nir.info.__bindgen_anon_1.gs };
|
||||
|
||||
@@ -59,34 +59,37 @@ fn init_info_from_nir(nir: &nir_shader, sm: u8) -> ShaderInfo {
|
||||
MESA_SHADER_TESS_EVAL => ShaderStageInfo::Tessellation,
|
||||
_ => panic!("Unknown shader stage"),
|
||||
},
|
||||
vtg_stage_info: match nir.info.stage() {
|
||||
MESA_SHADER_COMPUTE | MESA_SHADER_FRAGMENT => None,
|
||||
io: match nir.info.stage() {
|
||||
MESA_SHADER_COMPUTE => ShaderIoInfo::None,
|
||||
MESA_SHADER_FRAGMENT => ShaderIoInfo::Fragment(FragmentIoInfo {
|
||||
sysvals_in: SysValInfo {
|
||||
// Required on fragment shaders, otherwise it cause a trap.
|
||||
ab: 1 << 31,
|
||||
c: 0,
|
||||
},
|
||||
attr_in: [PixelImap::Unused; 128],
|
||||
reads_sample_mask: false,
|
||||
uses_kill: false,
|
||||
writes_color: 0,
|
||||
writes_sample_mask: false,
|
||||
writes_depth: false,
|
||||
}),
|
||||
MESA_SHADER_VERTEX
|
||||
| MESA_SHADER_GEOMETRY
|
||||
| MESA_SHADER_TESS_CTRL
|
||||
| MESA_SHADER_TESS_EVAL => Some(Default::default()),
|
||||
| MESA_SHADER_TESS_EVAL => ShaderIoInfo::Vtg(VtgIoInfo {
|
||||
sysvals_in: SysValInfo::default(),
|
||||
sysvals_out: SysValInfo::default(),
|
||||
attr_in: [0; 4],
|
||||
attr_out: [0; 4],
|
||||
|
||||
// TODO: figure out how to fill this.
|
||||
store_req_start: 0xff,
|
||||
store_req_end: 0,
|
||||
}),
|
||||
_ => panic!("Unknown shader stage"),
|
||||
},
|
||||
input_attributes: [0; 32],
|
||||
imap_color: 0,
|
||||
system_values_in: SystemValueInfo {
|
||||
ab: if nir.info.stage() == MESA_SHADER_FRAGMENT {
|
||||
// Required on fragment shaders, otherwise it cause a trap.
|
||||
1 << 31
|
||||
} else {
|
||||
0
|
||||
},
|
||||
c: 0,
|
||||
},
|
||||
};
|
||||
|
||||
if let Some(vtg_stage_info) = &mut res.vtg_stage_info {
|
||||
// TODO: figure out how to fill this.
|
||||
vtg_stage_info.store_req_start = 0xff;
|
||||
vtg_stage_info.store_req_end = 0x0;
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
fn alloc_ssa_for_nir(b: &mut impl SSABuilder, ssa: &nir_def) -> Vec<SSAValue> {
|
||||
@@ -1242,7 +1245,7 @@ impl<'a> ShaderFromNir<'a> {
|
||||
});
|
||||
}
|
||||
nir_intrinsic_demote | nir_intrinsic_discard => {
|
||||
if let ShaderStageInfo::Fragment(info) = &mut self.info.stage {
|
||||
if let ShaderIoInfo::Fragment(info) = &mut self.info.io {
|
||||
info.uses_kill = true;
|
||||
} else {
|
||||
panic!("OpKill is only available in fragment shaders");
|
||||
@@ -1250,7 +1253,7 @@ impl<'a> ShaderFromNir<'a> {
|
||||
b.push_op(OpKill {});
|
||||
}
|
||||
nir_intrinsic_demote_if | nir_intrinsic_discard_if => {
|
||||
if let ShaderStageInfo::Fragment(info) = &mut self.info.stage {
|
||||
if let ShaderIoInfo::Fragment(info) = &mut self.info.io {
|
||||
info.uses_kill = true;
|
||||
} else {
|
||||
panic!("OpKill is only available in fragment shaders");
|
||||
@@ -1338,67 +1341,101 @@ impl<'a> ShaderFromNir<'a> {
|
||||
let comps = intrin.def.num_components();
|
||||
let dst = b.alloc_ssa(RegFile::GPR, comps);
|
||||
|
||||
if self.nir.info.stage() == MESA_SHADER_FRAGMENT {
|
||||
assert!(intrin.intrinsic == nir_intrinsic_load_input);
|
||||
let addr = u16::try_from(intrin.base()).unwrap()
|
||||
+ u16::try_from(srcs[0].as_uint().unwrap()).unwrap()
|
||||
+ u16::try_from(intrin.component()).unwrap() * 4;
|
||||
// TODO: should be in the vtg block but we cannot have two mutability around.
|
||||
let (vtx, offset) = match intrin.intrinsic {
|
||||
nir_intrinsic_load_input => {
|
||||
(Src::new_zero(), self.get_src(&srcs[0]))
|
||||
}
|
||||
nir_intrinsic_load_per_vertex_input => {
|
||||
(self.get_src(&srcs[0]), self.get_src(&srcs[1]))
|
||||
}
|
||||
_ => panic!("Unhandled intrinsic"),
|
||||
};
|
||||
|
||||
for c in 0..comps {
|
||||
let attribute_id = addr + 4 * u16::from(c);
|
||||
self.info.set_used_attribute_id(
|
||||
attribute_id,
|
||||
None,
|
||||
false,
|
||||
);
|
||||
b.push_op(OpIpa {
|
||||
dst: dst[usize::from(c)].into(),
|
||||
addr: attribute_id,
|
||||
freq: InterpFreq::Constant,
|
||||
loc: InterpLoc::Default,
|
||||
offset: SrcRef::Zero.into(),
|
||||
match &mut self.info.io {
|
||||
ShaderIoInfo::None => {
|
||||
panic!("Stage does not support load_input")
|
||||
}
|
||||
ShaderIoInfo::Fragment(io) => {
|
||||
assert!(intrin.intrinsic == nir_intrinsic_load_input);
|
||||
let addr = u16::try_from(intrin.base()).unwrap()
|
||||
+ u16::try_from(srcs[0].as_uint().unwrap())
|
||||
.unwrap()
|
||||
+ u16::try_from(intrin.component()).unwrap() * 4;
|
||||
|
||||
for c in 0..comps {
|
||||
let attribute_id = addr + 4 * u16::from(c);
|
||||
|
||||
if attribute_id < 0x080 {
|
||||
io.sysvals_in.ab |= 1 << (attribute_id / 4);
|
||||
} else if attribute_id >= 0x080
|
||||
&& attribute_id < 0x280
|
||||
{
|
||||
let user_attribute_index =
|
||||
(attribute_id - 0x080) as usize / 4;
|
||||
|
||||
io.attr_in[user_attribute_index] =
|
||||
PixelImap::Constant;
|
||||
} else if attribute_id >= 0x2c0
|
||||
&& attribute_id < 0x300
|
||||
{
|
||||
io.sysvals_in.c |=
|
||||
1 << ((attribute_id - 0x2c0) / 4);
|
||||
}
|
||||
|
||||
b.push_op(OpIpa {
|
||||
dst: dst[usize::from(c)].into(),
|
||||
addr: attribute_id,
|
||||
freq: InterpFreq::Constant,
|
||||
loc: InterpLoc::Default,
|
||||
offset: SrcRef::Zero.into(),
|
||||
});
|
||||
}
|
||||
}
|
||||
ShaderIoInfo::Vtg(io) => {
|
||||
let addr = u16::try_from(intrin.base()).unwrap()
|
||||
+ u16::try_from(intrin.component()).unwrap() * 4;
|
||||
|
||||
let access = AttrAccess {
|
||||
addr: addr,
|
||||
comps: comps,
|
||||
patch: false,
|
||||
out_load: false,
|
||||
flags: 0,
|
||||
};
|
||||
|
||||
let attribute_base_index = access.addr / 4;
|
||||
for attribute_index in attribute_base_index
|
||||
..attribute_base_index + access.comps as u16
|
||||
{
|
||||
let attribute_id = attribute_index * 4;
|
||||
|
||||
if attribute_id < 0x080 {
|
||||
io.sysvals_in.ab |= 1 << (attribute_id / 4);
|
||||
} else if attribute_id >= 0x080
|
||||
&& attribute_id < 0x280
|
||||
{
|
||||
BitMutView::new(&mut io.attr_in).set_bit(
|
||||
(attribute_id as usize - 0x080) / 4,
|
||||
true,
|
||||
);
|
||||
} else if attribute_id >= 0x2c0
|
||||
&& attribute_id < 0x300
|
||||
{
|
||||
io.sysvals_in.c |=
|
||||
1 << ((attribute_id - 0x2c0) / 4);
|
||||
}
|
||||
}
|
||||
|
||||
b.push_op(OpALd {
|
||||
dst: dst.into(),
|
||||
vtx: vtx,
|
||||
offset: offset,
|
||||
access: access,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
let addr = u16::try_from(intrin.base()).unwrap()
|
||||
+ u16::try_from(intrin.component()).unwrap() * 4;
|
||||
|
||||
let (vtx, offset) = match intrin.intrinsic {
|
||||
nir_intrinsic_load_input => {
|
||||
(Src::new_zero(), self.get_src(&srcs[0]))
|
||||
}
|
||||
nir_intrinsic_load_per_vertex_input => {
|
||||
(self.get_src(&srcs[0]), self.get_src(&srcs[1]))
|
||||
}
|
||||
_ => panic!("Unhandled intrinsic"),
|
||||
};
|
||||
|
||||
let access = AttrAccess {
|
||||
addr: addr,
|
||||
comps: comps,
|
||||
patch: false,
|
||||
out_load: false,
|
||||
flags: 0,
|
||||
};
|
||||
|
||||
let attribute_base_index = access.addr / 4;
|
||||
for attribute_index in attribute_base_index
|
||||
..attribute_base_index + comps as u16
|
||||
{
|
||||
self.info.set_used_attribute_id(
|
||||
attribute_index * 4,
|
||||
None,
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
b.push_op(OpALd {
|
||||
dst: dst.into(),
|
||||
vtx: vtx,
|
||||
offset: offset,
|
||||
access: access,
|
||||
});
|
||||
}
|
||||
|
||||
self.set_dst(&intrin.def, dst);
|
||||
}
|
||||
nir_intrinsic_load_interpolated_input => {
|
||||
@@ -1410,7 +1447,7 @@ impl<'a> ShaderFromNir<'a> {
|
||||
let (freq, loc) = match bary.intrinsic {
|
||||
nir_intrinsic_load_barycentric_at_offset_nv => {
|
||||
(InterpFreq::Pass, InterpLoc::Offset)
|
||||
},
|
||||
}
|
||||
nir_intrinsic_load_barycentric_centroid => {
|
||||
(InterpFreq::Pass, InterpLoc::Centroid)
|
||||
}
|
||||
@@ -1443,11 +1480,57 @@ impl<'a> ShaderFromNir<'a> {
|
||||
|
||||
for c in 0..intrin.def.num_components() {
|
||||
let attribute_id = addr + 4 * u16::from(c);
|
||||
self.info.set_used_attribute_id(
|
||||
attribute_id,
|
||||
Some(interp_mode),
|
||||
false,
|
||||
);
|
||||
|
||||
if attribute_id < 0x080 {
|
||||
match &mut self.info.io {
|
||||
ShaderIoInfo::None => {
|
||||
panic!("Stage does not support load_interpolated_input")
|
||||
}
|
||||
ShaderIoInfo::Vtg(VtgIoInfo {
|
||||
sysvals_in, ..
|
||||
})
|
||||
| ShaderIoInfo::Fragment(FragmentIoInfo {
|
||||
sysvals_in,
|
||||
..
|
||||
}) => {
|
||||
sysvals_in.ab |= 1 << (attribute_id / 4);
|
||||
}
|
||||
}
|
||||
} else if attribute_id >= 0x080 && attribute_id < 0x280 {
|
||||
let user_attribute_index =
|
||||
(attribute_id - 0x080) as usize / 4;
|
||||
|
||||
match &mut self.info.io {
|
||||
ShaderIoInfo::None => {
|
||||
panic!("Stage does not support load_interpolated_input")
|
||||
}
|
||||
ShaderIoInfo::Vtg(io) => {
|
||||
BitMutView::new(&mut io.attr_in)
|
||||
.set_bit(user_attribute_index, true);
|
||||
}
|
||||
ShaderIoInfo::Fragment(io) => {
|
||||
io.attr_in[user_attribute_index] = interp_mode;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
} else if attribute_id >= 0x2c0 && attribute_id < 0x300 {
|
||||
match &mut self.info.io {
|
||||
ShaderIoInfo::None => {
|
||||
panic!("Stage does not support load_interpolated_input")
|
||||
}
|
||||
ShaderIoInfo::Vtg(VtgIoInfo {
|
||||
sysvals_in, ..
|
||||
})
|
||||
| ShaderIoInfo::Fragment(FragmentIoInfo {
|
||||
sysvals_in,
|
||||
..
|
||||
}) => {
|
||||
sysvals_in.c |=
|
||||
1 << ((attribute_id - 0x2c0) / 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b.push_op(OpIpa {
|
||||
dst: dst[usize::from(c)].into(),
|
||||
addr: attribute_id,
|
||||
@@ -1467,7 +1550,7 @@ impl<'a> ShaderFromNir<'a> {
|
||||
self.set_dst(&intrin.def, dst);
|
||||
}
|
||||
nir_intrinsic_load_sample_mask_in => {
|
||||
if let ShaderStageInfo::Fragment(info) = &mut self.info.stage {
|
||||
if let ShaderIoInfo::Fragment(info) = &mut self.info.io {
|
||||
info.reads_sample_mask = true;
|
||||
} else {
|
||||
panic!("sample_mask_in is only available in fragment shaders");
|
||||
@@ -1660,51 +1743,69 @@ impl<'a> ShaderFromNir<'a> {
|
||||
});
|
||||
}
|
||||
nir_intrinsic_store_output => {
|
||||
if self.nir.info.stage() == MESA_SHADER_FRAGMENT {
|
||||
/* We assume these only ever happen in the last block.
|
||||
* This is ensured by nir_lower_io_to_temporaries()
|
||||
*/
|
||||
let data = *self.get_src(&srcs[0]).as_ssa().unwrap();
|
||||
assert!(srcs[1].is_zero());
|
||||
let base: usize = intrin.base().try_into().unwrap();
|
||||
assert!(base % 4 == 0);
|
||||
for c in 0..usize::from(intrin.num_components) {
|
||||
self.fs_out_regs[(base / 4) + c] = data[c];
|
||||
let data = self.get_src(&srcs[0]);
|
||||
let vtx = Src::new_zero();
|
||||
let offset = self.get_src(&srcs[1]);
|
||||
|
||||
match &mut self.info.io {
|
||||
ShaderIoInfo::None => {
|
||||
panic!("Stage does not support load_input")
|
||||
}
|
||||
} else {
|
||||
let addr = u16::try_from(intrin.base()).unwrap()
|
||||
+ u16::try_from(intrin.component()).unwrap() * 4;
|
||||
|
||||
let data = self.get_src(&srcs[0]);
|
||||
let vtx = Src::new_zero();
|
||||
let offset = self.get_src(&srcs[1]);
|
||||
|
||||
assert!(intrin.get_src(0).bit_size() == 32);
|
||||
let access = AttrAccess {
|
||||
addr: addr,
|
||||
comps: intrin.get_src(0).num_components(),
|
||||
patch: false,
|
||||
out_load: false,
|
||||
flags: 0,
|
||||
};
|
||||
|
||||
let attribute_base_index = access.addr / 4;
|
||||
for attribute_index in attribute_base_index
|
||||
..attribute_base_index + access.comps as u16
|
||||
{
|
||||
self.info.set_used_attribute_id(
|
||||
attribute_index * 4,
|
||||
None,
|
||||
true,
|
||||
);
|
||||
ShaderIoInfo::Fragment(io) => {
|
||||
/* We assume these only ever happen in the last block.
|
||||
* This is ensured by nir_lower_io_to_temporaries()
|
||||
*/
|
||||
let data = *self.get_src(&srcs[0]).as_ssa().unwrap();
|
||||
assert!(srcs[1].is_zero());
|
||||
let base: usize = intrin.base().try_into().unwrap();
|
||||
assert!(base % 4 == 0);
|
||||
for c in 0..usize::from(intrin.num_components) {
|
||||
self.fs_out_regs[(base / 4) + c] = data[c];
|
||||
}
|
||||
}
|
||||
ShaderIoInfo::Vtg(io) => {
|
||||
let addr = u16::try_from(intrin.base()).unwrap()
|
||||
+ u16::try_from(intrin.component()).unwrap() * 4;
|
||||
|
||||
b.push_op(OpASt {
|
||||
vtx: vtx,
|
||||
offset: offset,
|
||||
data: data,
|
||||
access: access,
|
||||
});
|
||||
assert!(intrin.get_src(0).bit_size() == 32);
|
||||
let access = AttrAccess {
|
||||
addr: addr,
|
||||
comps: intrin.get_src(0).num_components(),
|
||||
patch: false,
|
||||
out_load: false,
|
||||
flags: 0,
|
||||
};
|
||||
|
||||
let attribute_base_index = access.addr / 4;
|
||||
for attribute_index in attribute_base_index
|
||||
..attribute_base_index + access.comps as u16
|
||||
{
|
||||
let attribute_id = attribute_index * 4;
|
||||
|
||||
if attribute_id < 0x080 {
|
||||
io.sysvals_out.ab |= 1 << (attribute_id / 4);
|
||||
} else if attribute_id >= 0x080
|
||||
&& attribute_id < 0x280
|
||||
{
|
||||
BitMutView::new(&mut io.attr_out).set_bit(
|
||||
(attribute_id as usize - 0x080) / 4,
|
||||
true,
|
||||
);
|
||||
} else if attribute_id >= 0x2c0
|
||||
&& attribute_id < 0x300
|
||||
{
|
||||
io.sysvals_out.c |=
|
||||
1 << ((attribute_id - 0x2c0) / 4);
|
||||
}
|
||||
}
|
||||
|
||||
b.push_op(OpASt {
|
||||
vtx: vtx,
|
||||
offset: offset,
|
||||
data: data,
|
||||
access: access,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
nir_intrinsic_store_scratch => {
|
||||
@@ -1801,7 +1902,7 @@ impl<'a> ShaderFromNir<'a> {
|
||||
}
|
||||
|
||||
fn store_fs_outputs(&mut self, b: &mut impl SSABuilder) {
|
||||
let ShaderStageInfo::Fragment(info) = &mut self.info.stage else {
|
||||
let ShaderIoInfo::Fragment(info) = &mut self.info.io else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
extern crate nak_ir_proc;
|
||||
|
||||
use crate::bitview::{BitMutView, SetField};
|
||||
pub use crate::nak_builder::{
|
||||
Builder, InstrBuilder, SSABuilder, SSAInstrBuilder,
|
||||
};
|
||||
@@ -4477,15 +4478,6 @@ pub struct ComputeShaderInfo {
|
||||
pub smem_size: u16,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct FragmentShaderInfo {
|
||||
pub reads_sample_mask: bool,
|
||||
pub uses_kill: bool,
|
||||
pub writes_color: u32,
|
||||
pub writes_sample_mask: bool,
|
||||
pub writes_depth: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct GeometryShaderInfo {
|
||||
pub stream_out_mask: u8,
|
||||
@@ -4515,25 +4507,45 @@ pub struct TessellationControlShaderInfo {
|
||||
pub enum ShaderStageInfo {
|
||||
Compute(ComputeShaderInfo),
|
||||
Vertex,
|
||||
Fragment(FragmentShaderInfo),
|
||||
Fragment,
|
||||
Geometry(GeometryShaderInfo),
|
||||
TessellationControl(TessellationControlShaderInfo),
|
||||
Tessellation,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct SystemValueInfo {
|
||||
pub struct SysValInfo {
|
||||
pub ab: u32,
|
||||
pub c: u16,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct ShaderStageVtgInfo {
|
||||
pub output_attributes: [u8; 32],
|
||||
#[derive(Debug)]
|
||||
pub struct VtgIoInfo {
|
||||
pub sysvals_in: SysValInfo,
|
||||
pub sysvals_out: SysValInfo,
|
||||
pub attr_in: [u32; 4],
|
||||
pub attr_out: [u32; 4],
|
||||
pub store_req_start: u8,
|
||||
pub store_req_end: u8,
|
||||
pub system_values_out: SystemValueInfo,
|
||||
pub omap_color: u16,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FragmentIoInfo {
|
||||
pub sysvals_in: SysValInfo,
|
||||
pub attr_in: [PixelImap; 128],
|
||||
|
||||
pub reads_sample_mask: bool,
|
||||
pub uses_kill: bool,
|
||||
pub writes_color: u32,
|
||||
pub writes_sample_mask: bool,
|
||||
pub writes_depth: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ShaderIoInfo {
|
||||
None,
|
||||
Vtg(VtgIoInfo),
|
||||
Fragment(FragmentIoInfo),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -4545,10 +4557,7 @@ pub struct ShaderInfo {
|
||||
pub writes_global_mem: bool,
|
||||
pub uses_fp64: bool,
|
||||
pub stage: ShaderStageInfo,
|
||||
pub vtg_stage_info: Option<ShaderStageVtgInfo>,
|
||||
pub input_attributes: [u8; 32],
|
||||
pub imap_color: u16,
|
||||
pub system_values_in: SystemValueInfo,
|
||||
pub io: ShaderIoInfo,
|
||||
}
|
||||
|
||||
pub struct Shader {
|
||||
@@ -4556,61 +4565,6 @@ pub struct Shader {
|
||||
pub functions: Vec<Function>,
|
||||
}
|
||||
|
||||
impl ShaderInfo {
|
||||
pub fn set_used_attribute_id(
|
||||
&mut self,
|
||||
attribute_id: u16,
|
||||
pixel_opt: Option<PixelImap>,
|
||||
is_store: bool,
|
||||
) {
|
||||
if attribute_id < 0x080 {
|
||||
let bit = attribute_id / 4;
|
||||
|
||||
if is_store {
|
||||
if let Some(vtg) = &mut self.vtg_stage_info {
|
||||
vtg.system_values_out.ab |= 1 << bit;
|
||||
}
|
||||
} else {
|
||||
self.system_values_in.ab |= 1 << bit;
|
||||
}
|
||||
} else if attribute_id >= 0x080 && attribute_id < 0x280 {
|
||||
let user_attribute_base = attribute_id - 0x080;
|
||||
let user_attribute_index = (user_attribute_base / 0x10) as usize;
|
||||
let user_attribute_component_bit_start =
|
||||
(user_attribute_base % 0x10) as usize / 4;
|
||||
|
||||
if let Some(vtg) = &mut self.vtg_stage_info {
|
||||
let attributes = if is_store {
|
||||
&mut vtg.output_attributes
|
||||
} else {
|
||||
&mut self.input_attributes
|
||||
};
|
||||
|
||||
attributes[user_attribute_index] |=
|
||||
1 << user_attribute_component_bit_start;
|
||||
} else if !is_store {
|
||||
if let ShaderStageInfo::Fragment(_) = &mut self.stage {
|
||||
let pixel = pixel_opt.unwrap_or(PixelImap::Perspective);
|
||||
|
||||
self.input_attributes[user_attribute_index] |=
|
||||
u8::from(pixel)
|
||||
<< user_attribute_component_bit_start * 2;
|
||||
}
|
||||
}
|
||||
} else if attribute_id >= 0x2c0 && attribute_id < 0x300 {
|
||||
let bit = (attribute_id - 0x2c0) / 4;
|
||||
|
||||
if is_store {
|
||||
if let Some(vtg) = &mut self.vtg_stage_info {
|
||||
vtg.system_values_out.c |= 1 << bit;
|
||||
}
|
||||
} else {
|
||||
self.system_values_in.c |= 1 << bit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Shader {
|
||||
pub fn for_each_instr(&self, f: &mut impl FnMut(&Instr)) {
|
||||
for func in &self.functions {
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::{
|
||||
BitMutView, BitMutViewable, BitView, BitViewable, SetBit, SetField,
|
||||
SetFieldU64,
|
||||
},
|
||||
nak_ir::{ShaderInfo, ShaderStageInfo},
|
||||
nak_ir::{ShaderInfo, ShaderIoInfo, ShaderStageInfo},
|
||||
};
|
||||
|
||||
pub const FERMI_SHADER_HEADER_SIZE: usize = 20;
|
||||
@@ -32,7 +32,7 @@ impl From<&ShaderStageInfo> for ShaderType {
|
||||
fn from(value: &ShaderStageInfo) -> Self {
|
||||
match value {
|
||||
ShaderStageInfo::Vertex => ShaderType::Vertex,
|
||||
ShaderStageInfo::Fragment(_) => ShaderType::Fragment,
|
||||
ShaderStageInfo::Fragment => ShaderType::Fragment,
|
||||
ShaderStageInfo::Geometry(_) => ShaderType::Geometry,
|
||||
ShaderStageInfo::TessellationControl(_) => {
|
||||
ShaderType::TessellationControl
|
||||
@@ -374,22 +374,21 @@ impl ShaderProgramHeader {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_imap_vector(&mut self, index: usize, value: u8) {
|
||||
assert!(index < 32);
|
||||
pub fn set_imap_vector_ps(&mut self, index: usize, value: PixelImap) {
|
||||
assert!(index < 128);
|
||||
assert!(self.shader_type == ShaderType::Fragment);
|
||||
|
||||
let (mut imap_g, elem_size) =
|
||||
if self.shader_type == ShaderType::Fragment {
|
||||
(self.imap_g_ps(), 8)
|
||||
} else {
|
||||
(self.imap_g_vtg(), 4)
|
||||
};
|
||||
|
||||
imap_g.set_field(index * elem_size..(index + 1) * elem_size, value);
|
||||
self.imap_g_ps()
|
||||
.set_field(index * 2..(index + 1) * 2, u8::from(value));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_imap_color(&mut self, value: u16) {
|
||||
self.set_field(320..336, value);
|
||||
pub fn set_imap_vector_vtg(&mut self, index: usize, value: u32) {
|
||||
assert!(index < 4);
|
||||
assert!(self.shader_type != ShaderType::Fragment);
|
||||
|
||||
self.imap_g_vtg()
|
||||
.set_field(index * 32..(index + 1) * 32, value);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -403,16 +402,11 @@ impl ShaderProgramHeader {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_omap_vector(&mut self, index: usize, value: u8) {
|
||||
assert!(index < 32);
|
||||
pub fn set_omap_vector(&mut self, index: usize, value: u32) {
|
||||
assert!(index < 4);
|
||||
assert!(self.shader_type != ShaderType::Fragment);
|
||||
|
||||
let (mut omap_g, elem_size) = (self.omap_g(), 4);
|
||||
omap_g.set_field(index * elem_size..(index + 1) * elem_size, value);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_omap_color(&mut self, value: u16) {
|
||||
self.set_field(560..576, value);
|
||||
self.omap_g().set_field(index * 32..(index + 1) * 32, value);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -452,41 +446,45 @@ pub fn encode_header(
|
||||
sph.set_does_fp64(shader_info.uses_fp64);
|
||||
sph.set_shader_local_memory_size(shader_info.tls_size.into());
|
||||
|
||||
sph.set_imap_system_values_ab(shader_info.system_values_in.ab);
|
||||
sph.set_imap_system_values_c(shader_info.system_values_in.c);
|
||||
match &shader_info.io {
|
||||
ShaderIoInfo::Vtg(io) => {
|
||||
sph.set_imap_system_values_ab(io.sysvals_in.ab);
|
||||
sph.set_imap_system_values_c(io.sysvals_in.c);
|
||||
|
||||
for (index, vec) in shader_info.input_attributes.iter().enumerate() {
|
||||
sph.set_imap_vector(index, *vec);
|
||||
}
|
||||
sph.set_imap_color(shader_info.imap_color);
|
||||
for (index, value) in io.attr_in.iter().enumerate() {
|
||||
sph.set_imap_vector_vtg(index, *value);
|
||||
}
|
||||
|
||||
if let Some(vtg_stage_info) = &shader_info.vtg_stage_info {
|
||||
for (index, vec) in vtg_stage_info.output_attributes.iter().enumerate()
|
||||
{
|
||||
sph.set_omap_vector(index, *vec);
|
||||
for (index, value) in io.attr_out.iter().enumerate() {
|
||||
sph.set_omap_vector(index, *value);
|
||||
}
|
||||
|
||||
sph.set_store_req_start(io.store_req_start);
|
||||
sph.set_store_req_end(io.store_req_end);
|
||||
|
||||
sph.set_omap_system_values_ab(io.sysvals_out.ab);
|
||||
sph.set_omap_system_values_c(io.sysvals_out.c);
|
||||
}
|
||||
sph.set_omap_color(vtg_stage_info.omap_color);
|
||||
ShaderIoInfo::Fragment(io) => {
|
||||
sph.set_imap_system_values_ab(io.sysvals_in.ab);
|
||||
sph.set_imap_system_values_c(io.sysvals_in.c);
|
||||
|
||||
sph.set_store_req_start(vtg_stage_info.store_req_start);
|
||||
sph.set_store_req_end(vtg_stage_info.store_req_end);
|
||||
for (index, imap) in io.attr_in.iter().enumerate() {
|
||||
sph.set_imap_vector_ps(index, *imap);
|
||||
}
|
||||
|
||||
sph.set_omap_system_values_ab(vtg_stage_info.system_values_out.ab);
|
||||
sph.set_omap_system_values_c(vtg_stage_info.system_values_out.c);
|
||||
let zs_self_dep = fs_key.map_or(false, |key| key.zs_self_dep);
|
||||
|
||||
sph.set_multiple_render_target_enable(io.writes_color > 0xf);
|
||||
sph.set_kills_pixels(io.uses_kill || zs_self_dep);
|
||||
sph.set_omap_sample_mask(io.writes_sample_mask);
|
||||
sph.set_omap_depth(io.writes_depth);
|
||||
sph.set_omap_targets(io.writes_color);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
match &shader_info.stage {
|
||||
// Already covered by VTG common data.
|
||||
ShaderStageInfo::Vertex | ShaderStageInfo::Tessellation => {}
|
||||
ShaderStageInfo::Fragment(stage) => {
|
||||
let zs_self_dep = fs_key.map_or(false, |key| key.zs_self_dep);
|
||||
|
||||
sph.set_multiple_render_target_enable(stage.writes_color > 0xf);
|
||||
sph.set_kills_pixels(stage.uses_kill || zs_self_dep);
|
||||
sph.set_omap_sample_mask(stage.writes_sample_mask);
|
||||
sph.set_omap_depth(stage.writes_depth);
|
||||
|
||||
sph.set_omap_targets(stage.writes_color);
|
||||
}
|
||||
ShaderStageInfo::Geometry(stage) => {
|
||||
sph.set_stream_out_mask(stage.stream_out_mask);
|
||||
sph.set_threads_per_input_primitive(
|
||||
@@ -502,6 +500,7 @@ pub fn encode_header(
|
||||
ShaderStageInfo::Compute(_) => {
|
||||
panic!("Compute shaders don't have a SPH!")
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
||||
sph.data
|
||||
|
||||
Reference in New Issue
Block a user