nak: Implement load_tess_coord

We could lower this to load_per_vertex_output in NIR but then it
confuses all sorts of NIR passes which assume load_*output only
happens in control shaders.  We could also add a magic NIR intrinsic
but it's probably easier to just special-case this one.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24998>
This commit is contained in:
Faith Ekstrand 2023-10-02 13:23:54 -05:00 committed by Marge Bot
parent b5cb508523
commit efbbc3ed93
2 changed files with 61 additions and 1 deletions

View file

@ -1623,6 +1623,48 @@ impl<'a> ShaderFromNir<'a> {
});
self.set_dst(&intrin.def, dst);
}
nir_intrinsic_load_tess_coord_xy => {
// Loading gl_TessCoord in tessellation evaluation shaders is
// weird. It's treated as a per-vertex output which is indexed
// by LANEID.
match &self.info.stage {
ShaderStageInfo::Tessellation => (),
_ => panic!(
"load_tess_coord is only available in tessellation \
shaders"
),
};
assert!(intrin.def.bit_size() == 32);
assert!(intrin.def.num_components() == 2);
let vtx = b.alloc_ssa(RegFile::GPR, 1);
b.push_op(OpS2R {
dst: vtx.into(),
idx: 0,
});
let access = AttrAccess {
addr: NAK_ATTR_TESS_COORD,
comps: 2,
patch: false,
output: true,
flags: 0,
};
// This is recorded as a patch output in parse_shader() because
// the hardware requires it be in the SPH, whether we use it or
// not.
let dst = b.alloc_ssa(RegFile::GPR, access.comps);
b.push_op(OpALd {
dst: dst.into(),
vtx: vtx.into(),
offset: 0.into(),
access: access,
});
self.set_dst(&intrin.def, dst);
}
nir_intrinsic_load_scratch => {
let size_B =
(intrin.def.bit_size() / 8) * intrin.def.num_components();
@ -2178,6 +2220,20 @@ impl<'a> ShaderFromNir<'a> {
functions.push(f);
}
}
// Tessellation evaluation shaders MUST claim to read gl_TessCoord or
// the hardware will throw an SPH error.
match &self.info.stage {
ShaderStageInfo::Tessellation => match &mut self.info.io {
ShaderIoInfo::Vtg(io) => {
let tc = NAK_ATTR_TESS_COORD;
io.mark_attrs_written(tc..(tc + 8));
}
_ => panic!("Tessellation must have ShaderIoInfo::Vtg"),
}
_ => ()
}
Shader {
info: self.info,
functions: functions,

View file

@ -612,7 +612,6 @@ nak_nir_lower_system_value_instr(nir_builder *b, nir_instr *instr, void *data)
}
case nir_intrinsic_load_front_face:
case nir_intrinsic_load_tess_coord:
case nir_intrinsic_load_instance_id:
case nir_intrinsic_load_vertex_id: {
const gl_system_value sysval =
@ -791,6 +790,11 @@ nak_postprocess_nir(nir_shader *nir,
unreachable("Unsupported shader stage");
}
if (nir->info.stage == MESA_SHADER_TESS_EVAL) {
OPT(nir, nir_lower_tess_coord_z,
nir->info.tess._primitive_mode == TESS_PRIMITIVE_TRIANGLES);
}
OPT(nir, nak_nir_lower_system_values);
nak_optimize_nir(nir, nak);