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:
Mary Guillemard
2023-09-26 17:44:24 +02:00
committed by Marge Bot
parent 267a4f07d0
commit 145213fd2c
4 changed files with 321 additions and 261 deletions
+7 -1
View File
@@ -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 {
+236 -135
View File
@@ -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;
};
+29 -75
View File
@@ -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 {
+49 -50
View File
@@ -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