Skip to content

Commit ad8e68e

Browse files
roamicXcedf
authored andcommitted
recompiler: fixed fragment shader built-in attribute access (shadps4-emu#1676)
* recompiler: fixed fragment shader built-in attribute access * handle en/addr separately * handle other registers as well
1 parent f495d2a commit ad8e68e

File tree

4 files changed

+101
-9
lines changed

4 files changed

+101
-9
lines changed

src/shader_recompiler/frontend/translate/translate.cpp

Lines changed: 67 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,74 @@ void Translator::EmitPrologue() {
5353
}
5454
break;
5555
case Stage::Fragment:
56-
// https://github.com/chaotic-cx/mesa-mirror/blob/72326e15/src/amd/vulkan/radv_shader_args.c#L258
57-
// The first two VGPRs are used for i/j barycentric coordinates. In the vast majority of
58-
// cases it will be only those two, but if shader is using both e.g linear and perspective
59-
// inputs it can be more For now assume that this isn't the case.
60-
dst_vreg = IR::VectorReg::V2;
61-
for (u32 i = 0; i < 4; i++) {
62-
ir.SetVectorReg(dst_vreg++, ir.GetAttribute(IR::Attribute::FragCoord, i));
56+
dst_vreg = IR::VectorReg::V0;
57+
if (runtime_info.fs_info.addr_flags.persp_sample_ena) {
58+
++dst_vreg; // I
59+
++dst_vreg; // J
60+
}
61+
if (runtime_info.fs_info.addr_flags.persp_center_ena) {
62+
++dst_vreg; // I
63+
++dst_vreg; // J
64+
}
65+
if (runtime_info.fs_info.addr_flags.persp_centroid_ena) {
66+
++dst_vreg; // I
67+
++dst_vreg; // J
68+
}
69+
if (runtime_info.fs_info.addr_flags.persp_pull_model_ena) {
70+
++dst_vreg; // I/W
71+
++dst_vreg; // J/W
72+
++dst_vreg; // 1/W
73+
}
74+
if (runtime_info.fs_info.addr_flags.linear_sample_ena) {
75+
++dst_vreg; // I
76+
++dst_vreg; // J
77+
}
78+
if (runtime_info.fs_info.addr_flags.linear_center_ena) {
79+
++dst_vreg; // I
80+
++dst_vreg; // J
81+
}
82+
if (runtime_info.fs_info.addr_flags.linear_centroid_ena) {
83+
++dst_vreg; // I
84+
++dst_vreg; // J
85+
}
86+
if (runtime_info.fs_info.addr_flags.line_stipple_tex_ena) {
87+
++dst_vreg;
88+
}
89+
if (runtime_info.fs_info.addr_flags.pos_x_float_ena) {
90+
if (runtime_info.fs_info.en_flags.pos_x_float_ena) {
91+
ir.SetVectorReg(dst_vreg++, ir.GetAttribute(IR::Attribute::FragCoord, 0));
92+
} else {
93+
ir.SetVectorReg(dst_vreg++, ir.Imm32(0.0f));
94+
}
95+
}
96+
if (runtime_info.fs_info.addr_flags.pos_y_float_ena) {
97+
if (runtime_info.fs_info.en_flags.pos_y_float_ena) {
98+
ir.SetVectorReg(dst_vreg++, ir.GetAttribute(IR::Attribute::FragCoord, 1));
99+
} else {
100+
ir.SetVectorReg(dst_vreg++, ir.Imm32(0.0f));
101+
}
102+
}
103+
if (runtime_info.fs_info.addr_flags.pos_z_float_ena) {
104+
if (runtime_info.fs_info.en_flags.pos_z_float_ena) {
105+
ir.SetVectorReg(dst_vreg++, ir.GetAttribute(IR::Attribute::FragCoord, 2));
106+
} else {
107+
ir.SetVectorReg(dst_vreg++, ir.Imm32(0.0f));
108+
}
109+
}
110+
if (runtime_info.fs_info.addr_flags.pos_w_float_ena) {
111+
if (runtime_info.fs_info.en_flags.pos_w_float_ena) {
112+
ir.SetVectorReg(dst_vreg++, ir.GetAttribute(IR::Attribute::FragCoord, 3));
113+
} else {
114+
ir.SetVectorReg(dst_vreg++, ir.Imm32(0.0f));
115+
}
116+
}
117+
if (runtime_info.fs_info.addr_flags.front_face_ena) {
118+
if (runtime_info.fs_info.en_flags.front_face_ena) {
119+
ir.SetVectorReg(dst_vreg++, ir.GetAttributeU32(IR::Attribute::IsFrontFace));
120+
} else {
121+
ir.SetVectorReg(dst_vreg++, ir.Imm32(0));
122+
}
63123
}
64-
ir.SetVectorReg(dst_vreg++, ir.GetAttributeU32(IR::Attribute::IsFrontFace));
65124
break;
66125
case Stage::Compute:
67126
ir.SetVectorReg(dst_vreg++, ir.GetAttributeU32(IR::Attribute::LocalInvocationId, 0));

src/shader_recompiler/runtime_info.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <span>
88
#include <boost/container/static_vector.hpp>
99
#include "common/types.h"
10+
#include "video_core/amdgpu/liverpool.h"
1011
#include "video_core/amdgpu/types.h"
1112

1213
namespace Shader {
@@ -105,6 +106,8 @@ struct FragmentRuntimeInfo {
105106

106107
auto operator<=>(const PsInput&) const noexcept = default;
107108
};
109+
AmdGpu::Liverpool::PsInput en_flags;
110+
AmdGpu::Liverpool::PsInput addr_flags;
108111
u32 num_inputs;
109112
std::array<PsInput, 32> inputs;
110113
struct PsColorBuffer {
@@ -117,6 +120,7 @@ struct FragmentRuntimeInfo {
117120

118121
bool operator==(const FragmentRuntimeInfo& other) const noexcept {
119122
return std::ranges::equal(color_buffers, other.color_buffers) &&
123+
en_flags.raw == other.en_flags.raw && addr_flags.raw == other.addr_flags.raw &&
120124
num_inputs == other.num_inputs &&
121125
std::ranges::equal(inputs.begin(), inputs.begin() + num_inputs, other.inputs.begin(),
122126
other.inputs.begin() + num_inputs);

src/video_core/amdgpu/liverpool.h

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1071,6 +1071,28 @@ struct Liverpool {
10711071
BitField<27, 1, u32> enable_postz_overrasterization;
10721072
};
10731073

1074+
union PsInput {
1075+
u32 raw;
1076+
struct {
1077+
u32 persp_sample_ena : 1;
1078+
u32 persp_center_ena : 1;
1079+
u32 persp_centroid_ena : 1;
1080+
u32 persp_pull_model_ena : 1;
1081+
u32 linear_sample_ena : 1;
1082+
u32 linear_center_ena : 1;
1083+
u32 linear_centroid_ena : 1;
1084+
u32 line_stipple_tex_ena : 1;
1085+
u32 pos_x_float_ena : 1;
1086+
u32 pos_y_float_ena : 1;
1087+
u32 pos_z_float_ena : 1;
1088+
u32 pos_w_float_ena : 1;
1089+
u32 front_face_ena : 1;
1090+
u32 ancillary_ena : 1;
1091+
u32 sample_coverage_ena : 1;
1092+
u32 pos_fixed_pt_ena : 1;
1093+
};
1094+
};
1095+
10741096
union Regs {
10751097
struct {
10761098
INSERT_PADDING_WORDS(0x2C08);
@@ -1126,7 +1148,10 @@ struct Liverpool {
11261148
INSERT_PADDING_WORDS(0xA191 - 0xA187);
11271149
std::array<PsInputControl, 32> ps_inputs;
11281150
VsOutputConfig vs_output_config;
1129-
INSERT_PADDING_WORDS(4);
1151+
INSERT_PADDING_WORDS(1);
1152+
PsInput ps_input_ena;
1153+
PsInput ps_input_addr;
1154+
INSERT_PADDING_WORDS(1);
11301155
BitField<0, 6, u32> num_interp;
11311156
INSERT_PADDING_WORDS(0xA1C3 - 0xA1B6 - 1);
11321157
ShaderPosFormat shader_pos_format;
@@ -1388,6 +1413,8 @@ static_assert(GFX6_3D_REG_INDEX(viewports) == 0xA10F);
13881413
static_assert(GFX6_3D_REG_INDEX(clip_user_data) == 0xA16F);
13891414
static_assert(GFX6_3D_REG_INDEX(ps_inputs) == 0xA191);
13901415
static_assert(GFX6_3D_REG_INDEX(vs_output_config) == 0xA1B1);
1416+
static_assert(GFX6_3D_REG_INDEX(ps_input_ena) == 0xA1B3);
1417+
static_assert(GFX6_3D_REG_INDEX(ps_input_addr) == 0xA1B4);
13911418
static_assert(GFX6_3D_REG_INDEX(num_interp) == 0xA1B6);
13921419
static_assert(GFX6_3D_REG_INDEX(shader_pos_format) == 0xA1C3);
13931420
static_assert(GFX6_3D_REG_INDEX(z_export_format) == 0xA1C4);

src/video_core/renderer_vulkan/vk_pipeline_cache.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ Shader::RuntimeInfo PipelineCache::BuildRuntimeInfo(Shader::Stage stage) {
123123
}
124124
case Shader::Stage::Fragment: {
125125
BuildCommon(regs.ps_program);
126+
info.fs_info.en_flags = regs.ps_input_ena;
127+
info.fs_info.addr_flags = regs.ps_input_addr;
126128
const auto& ps_inputs = regs.ps_inputs;
127129
info.fs_info.num_inputs = regs.num_interp;
128130
for (u32 i = 0; i < regs.num_interp; i++) {

0 commit comments

Comments
 (0)