diff --git a/src/shader_recompiler/frontend/translate/translate.cpp b/src/shader_recompiler/frontend/translate/translate.cpp index 68625a12b..8e16d848b 100644 --- a/src/shader_recompiler/frontend/translate/translate.cpp +++ b/src/shader_recompiler/frontend/translate/translate.cpp @@ -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++) { - ir.SetVectorReg(dst_vreg++, ir.GetAttribute(IR::Attribute::FragCoord, 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)); } - ir.SetVectorReg(dst_vreg++, ir.GetAttributeU32(IR::Attribute::IsFrontFace)); break; case Stage::Compute: ir.SetVectorReg(dst_vreg++, ir.GetAttributeU32(IR::Attribute::LocalInvocationId, 0)); diff --git a/src/shader_recompiler/runtime_info.h b/src/shader_recompiler/runtime_info.h index 4662def93..67ccaf6a8 100644 --- a/src/shader_recompiler/runtime_info.h +++ b/src/shader_recompiler/runtime_info.h @@ -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 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); } diff --git a/src/video_core/amdgpu/liverpool.h b/src/video_core/amdgpu/liverpool.h index 2b2f2c00a..60689f16f 100644 --- a/src/video_core/amdgpu/liverpool.h +++ b/src/video_core/amdgpu/liverpool.h @@ -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 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); diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 47713f0ff..7e7f9c1a8 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -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++) {