recompiler: fixed fragment shader built-in attribute access

This commit is contained in:
Vladislav Mikhalin 2024-12-06 19:28:26 +03:00
parent 17abbcd74d
commit ceeca3d718
4 changed files with 59 additions and 4 deletions

View File

@ -59,9 +59,13 @@ void Translator::EmitPrologue() {
// inputs it can be more For now assume that this isn't the case.
dst_vreg = IR::VectorReg::V2;
for (u32 i = 0; i < 4; i++) {
if (True(runtime_info.fs_info.en_flags & Shader::PsInputEnableFlags(1 << i))) {
ir.SetVectorReg(dst_vreg++, ir.GetAttribute(IR::Attribute::FragCoord, i));
}
}
if (True(runtime_info.fs_info.en_flags & Shader::PsInputEnableFlags::FrontFacing)) {
ir.SetVectorReg(dst_vreg++, ir.GetAttributeU32(IR::Attribute::IsFrontFace));
}
break;
case Stage::Compute:
ir.SetVectorReg(dst_vreg++, ir.GetAttributeU32(IR::Attribute::LocalInvocationId, 0));

View File

@ -96,6 +96,16 @@ enum class MrtSwizzle : u8 {
};
static constexpr u32 MaxColorBuffers = 8;
enum class PsInputEnableFlags : u8 {
None = 0,
PosX = 1 << 0,
PosY = 1 << 1,
PosZ = 1 << 2,
PosW = 1 << 3,
FrontFacing = 1 << 4,
};
DECLARE_ENUM_FLAG_OPERATORS(PsInputEnableFlags)
struct FragmentRuntimeInfo {
struct PsInput {
u8 param_index;
@ -105,6 +115,7 @@ struct FragmentRuntimeInfo {
auto operator<=>(const PsInput&) const noexcept = default;
};
PsInputEnableFlags en_flags;
u32 num_inputs;
std::array<PsInput, 32> inputs;
struct PsColorBuffer {
@ -117,7 +128,7 @@ struct FragmentRuntimeInfo {
bool operator==(const FragmentRuntimeInfo& other) const noexcept {
return std::ranges::equal(color_buffers, other.color_buffers) &&
num_inputs == other.num_inputs &&
en_flags == other.en_flags && num_inputs == other.num_inputs &&
std::ranges::equal(inputs.begin(), inputs.begin() + num_inputs, other.inputs.begin(),
other.inputs.begin() + num_inputs);
}

View File

@ -1071,6 +1071,25 @@ struct Liverpool {
BitField<27, 1, u32> enable_postz_overrasterization;
};
struct PsInput {
u32 persp_sample_ena : 1;
u32 persp_center_ena : 1;
u32 persp_centroid_ena : 1;
u32 persp_pull_model_ena : 1;
u32 linear_sample_ena : 1;
u32 linear_center_ena : 1;
u32 linear_centroid_ena : 1;
u32 line_stipple_tex_ena : 1;
u32 pos_x_float_ena : 1;
u32 pos_y_float_ena : 1;
u32 pos_z_float_ena : 1;
u32 pos_w_float_ena : 1;
u32 front_face_ena : 1;
u32 ancillary_ena : 1;
u32 sample_coverage_ena : 1;
u32 pos_fixed_pt_ena : 1;
};
union Regs {
struct {
INSERT_PADDING_WORDS(0x2C08);
@ -1126,7 +1145,10 @@ struct Liverpool {
INSERT_PADDING_WORDS(0xA191 - 0xA187);
std::array<PsInputControl, 32> ps_inputs;
VsOutputConfig vs_output_config;
INSERT_PADDING_WORDS(4);
INSERT_PADDING_WORDS(1);
PsInput ps_input_ena;
PsInput ps_input_addr;
INSERT_PADDING_WORDS(1);
BitField<0, 6, u32> num_interp;
INSERT_PADDING_WORDS(0xA1C3 - 0xA1B6 - 1);
ShaderPosFormat shader_pos_format;
@ -1388,6 +1410,8 @@ static_assert(GFX6_3D_REG_INDEX(viewports) == 0xA10F);
static_assert(GFX6_3D_REG_INDEX(clip_user_data) == 0xA16F);
static_assert(GFX6_3D_REG_INDEX(ps_inputs) == 0xA191);
static_assert(GFX6_3D_REG_INDEX(vs_output_config) == 0xA1B1);
static_assert(GFX6_3D_REG_INDEX(ps_input_ena) == 0xA1B3);
static_assert(GFX6_3D_REG_INDEX(ps_input_addr) == 0xA1B4);
static_assert(GFX6_3D_REG_INDEX(num_interp) == 0xA1B6);
static_assert(GFX6_3D_REG_INDEX(shader_pos_format) == 0xA1C3);
static_assert(GFX6_3D_REG_INDEX(z_export_format) == 0xA1C4);

View File

@ -123,6 +123,22 @@ Shader::RuntimeInfo PipelineCache::BuildRuntimeInfo(Shader::Stage stage) {
}
case Shader::Stage::Fragment: {
BuildCommon(regs.ps_program);
info.fs_info.en_flags =
((regs.ps_input_addr.pos_x_float_ena && regs.ps_input_ena.pos_x_float_ena)
? Shader::PsInputEnableFlags::PosX
: Shader::PsInputEnableFlags::None) |
((regs.ps_input_addr.pos_y_float_ena && regs.ps_input_ena.pos_y_float_ena)
? Shader::PsInputEnableFlags::PosY
: Shader::PsInputEnableFlags::None) |
((regs.ps_input_addr.pos_z_float_ena && regs.ps_input_ena.pos_z_float_ena)
? Shader::PsInputEnableFlags::PosZ
: Shader::PsInputEnableFlags::None) |
((regs.ps_input_addr.pos_w_float_ena && regs.ps_input_ena.pos_w_float_ena)
? Shader::PsInputEnableFlags::PosW
: Shader::PsInputEnableFlags::None) |
((regs.ps_input_addr.front_face_ena && regs.ps_input_ena.front_face_ena)
? Shader::PsInputEnableFlags::FrontFacing
: Shader::PsInputEnableFlags::None);
const auto& ps_inputs = regs.ps_inputs;
info.fs_info.num_inputs = regs.num_interp;
for (u32 i = 0; i < regs.num_interp; i++) {