control fix?

This commit is contained in:
Marcin Mikołajczyk 2026-05-07 19:06:03 +02:00
parent d85a5013ec
commit e44e7f0cdf
4 changed files with 49 additions and 6 deletions

View File

@ -144,6 +144,25 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, u32 comp, u32 index) {
case IR::Attribute::BaryCoordNoPersp:
return ctx.OpLoad(ctx.F32[1], ctx.OpAccessChain(ctx.input_f32, ctx.bary_coord_nopersp,
ctx.ConstU32(comp)));
case IR::Attribute::BaryCoordPullModel:
if (ctx.profile.supports_amd_shader_explicit_vertex_parameter) {
return ctx.OpLoad(ctx.F32[1], ctx.OpAccessChain(ctx.input_f32, ctx.bary_coord_pullmodel,
ctx.ConstU32(comp)));
} else {
switch (comp) {
case 0:
return ctx.OpLoad(
ctx.F32[1], ctx.OpAccessChain(ctx.input_f32, ctx.frag_coord, ctx.ConstU32(3U)));
case 1:
case 2:
return ctx.OpFDiv(
ctx.F32[1], ctx.ConstF32(1.0f),
ctx.OpLoad(ctx.F32[1], ctx.OpAccessChain(ctx.input_f32, ctx.bary_coord_nopersp,
ctx.ConstU32(comp))));
default:
UNREACHABLE_MSG("BaryCoordPullModel comp {}", comp);
}
}
default:
UNREACHABLE_MSG("Read attribute {}", attr);
}

View File

@ -418,6 +418,15 @@ void EmitContext::DefineInputs() {
spv::StorageClass::Input);
}
}
if (info.loads.GetAny(IR::Attribute::BaryCoordPullModel)) {
if (profile.supports_amd_shader_explicit_vertex_parameter) {
bary_coord_pullmodel = DefineVariable(F32[3], spv::BuiltIn::BaryCoordPullModelAMD,
spv::StorageClass::Input);
} else if (profile.supports_fragment_shader_barycentric) {
bary_coord_nopersp = DefineVariable(F32[3], spv::BuiltIn::BaryCoordNoPerspKHR,
spv::StorageClass::Input);
}
}
const bool has_clip_distance_inputs = runtime_info.fs_info.clip_distance_emulation;
// Clip distances attribute vector is the last in inputs array

View File

@ -288,6 +288,7 @@ public:
Id bary_coord_smooth_centroid{};
Id bary_coord_smooth_sample{};
Id bary_coord_nopersp{};
Id bary_coord_pullmodel{};
struct TextureDefinition {
const VectorIds* data_types;

View File

@ -98,14 +98,28 @@ void Translator::V_INTERP_MOV_F32(const GcnInst& inst) {
const IR::Attribute attrib = IR::Attribute::Param0 + attr_index;
const auto& attr = runtime_info.fs_info.inputs[attr_index];
auto& interp = info.fs_interpolation[attr_index];
ASSERT(attr.is_flat || inst.src[0].code == 2);
if (profile.supports_amd_shader_explicit_vertex_parameter ||
(profile.supports_fragment_shader_barycentric &&
!profile.has_incomplete_fragment_shader_barycentric)) {
if (!attr.is_flat && (profile.supports_amd_shader_explicit_vertex_parameter ||
(profile.supports_fragment_shader_barycentric &&
!profile.has_incomplete_fragment_shader_barycentric))) {
// VSRC 0=P10, 1=P20, 2=P0
interp.primary = Qualifier::PerVertex;
SetDst(inst.dst[0],
ir.GetAttribute(attrib, inst.control.vintrp.chan, (inst.src[0].code + 1) % 3));
switch (inst.src[0].code) {
case 0: { // P10
const IR::F32 p0 = ir.GetAttribute(attrib, inst.control.vintrp.chan, 0);
const IR::F32 p1 = ir.GetAttribute(attrib, inst.control.vintrp.chan, 1);
return SetDst(inst.dst[0], ir.FPSub(p1, p0));
}
case 1: { // P20
const IR::F32 p0 = ir.GetAttribute(attrib, inst.control.vintrp.chan, 0);
const IR::F32 p2 = ir.GetAttribute(attrib, inst.control.vintrp.chan, 2);
return SetDst(inst.dst[0], ir.FPSub(p2, p0));
}
case 2: // P0
return SetDst(inst.dst[0], ir.GetAttribute(attrib, inst.control.vintrp.chan, 0));
default:
UNREACHABLE();
}
} else {
interp.primary = Qualifier::Flat;
SetDst(inst.dst[0], ir.GetAttribute(attrib, inst.control.vintrp.chan));