From 81a5062ee95dea6e8075345a9a1f3d9d916a4a5a Mon Sep 17 00:00:00 2001 From: Vladislav Mikhalin Date: Fri, 6 Dec 2024 20:34:00 +0300 Subject: [PATCH] handle other registers as well --- .../frontend/translate/translate.cpp | 81 ++++++++++++++----- src/shader_recompiler/runtime_info.h | 17 +--- src/video_core/amdgpu/liverpool.h | 37 +++++---- .../renderer_vulkan/vk_pipeline_cache.cpp | 24 +----- 4 files changed, 89 insertions(+), 70 deletions(-) diff --git a/src/shader_recompiler/frontend/translate/translate.cpp b/src/shader_recompiler/frontend/translate/translate.cpp index df5cf8a1a..b3a47fde8 100644 --- a/src/shader_recompiler/frontend/translate/translate.cpp +++ b/src/shader_recompiler/frontend/translate/translate.cpp @@ -53,28 +53,73 @@ void Translator::EmitPrologue() { } break; case Stage::Fragment: - // https://github.com/chaotic-cx/mesa-mirror/blob/72326e15/src/amd/vulkan/radv_shader_args.c#L258 - // The first two VGPRs are used for i/j barycentric coordinates. In the vast majority of - // cases it will be only those two, but if shader is using both e.g linear and perspective - // 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.addr_flags & Shader::PsInputFlags(1 << i))) { - if (True(runtime_info.fs_info.en_flags & Shader::PsInputFlags(1 << i))) { - ir.SetVectorReg(dst_vreg, ir.GetAttribute(IR::Attribute::FragCoord, i)); - } else { - ir.SetVectorReg(dst_vreg, ir.Imm32(0.0f)); - } - ++dst_vreg; + dst_vreg = IR::VectorReg::V0; + if (runtime_info.fs_info.addr_flags.persp_sample_ena) { + ++dst_vreg; // I + ++dst_vreg; // J + } + if (runtime_info.fs_info.addr_flags.persp_center_ena) { + ++dst_vreg; // I + ++dst_vreg; // J + } + if (runtime_info.fs_info.addr_flags.persp_centroid_ena) { + ++dst_vreg; // I + ++dst_vreg; // J + } + if (runtime_info.fs_info.addr_flags.persp_pull_model_ena) { + ++dst_vreg; // I/W + ++dst_vreg; // J/W + ++dst_vreg; // 1/W + } + if (runtime_info.fs_info.addr_flags.linear_sample_ena) { + ++dst_vreg; // I + ++dst_vreg; // J + } + if (runtime_info.fs_info.addr_flags.linear_center_ena) { + ++dst_vreg; // I + ++dst_vreg; // J + } + if (runtime_info.fs_info.addr_flags.linear_centroid_ena) { + ++dst_vreg; // I + ++dst_vreg; // J + } + if (runtime_info.fs_info.addr_flags.line_stipple_tex_ena) { + ++dst_vreg; + } + if (runtime_info.fs_info.addr_flags.pos_x_float_ena) { + if (runtime_info.fs_info.en_flags.pos_x_float_ena) { + ir.SetVectorReg(dst_vreg++, ir.GetAttribute(IR::Attribute::FragCoord, 0)); + } else { + ir.SetVectorReg(dst_vreg++, ir.Imm32(0.0f)); } } - if (True(runtime_info.fs_info.addr_flags & Shader::PsInputFlags::FrontFacing)) { - if (True(runtime_info.fs_info.en_flags & Shader::PsInputFlags::FrontFacing)) { - ir.SetVectorReg(dst_vreg, ir.GetAttributeU32(IR::Attribute::IsFrontFace)); + if (runtime_info.fs_info.addr_flags.pos_y_float_ena) { + if (runtime_info.fs_info.en_flags.pos_y_float_ena) { + ir.SetVectorReg(dst_vreg++, ir.GetAttribute(IR::Attribute::FragCoord, 1)); } else { - ir.SetVectorReg(dst_vreg, ir.Imm32(0)); + ir.SetVectorReg(dst_vreg++, ir.Imm32(0.0f)); + } + } + if (runtime_info.fs_info.addr_flags.pos_z_float_ena) { + if (runtime_info.fs_info.en_flags.pos_z_float_ena) { + ir.SetVectorReg(dst_vreg++, ir.GetAttribute(IR::Attribute::FragCoord, 2)); + } else { + ir.SetVectorReg(dst_vreg++, ir.Imm32(0.0f)); + } + } + if (runtime_info.fs_info.addr_flags.pos_w_float_ena) { + if (runtime_info.fs_info.en_flags.pos_w_float_ena) { + ir.SetVectorReg(dst_vreg++, ir.GetAttribute(IR::Attribute::FragCoord, 3)); + } else { + ir.SetVectorReg(dst_vreg++, ir.Imm32(0.0f)); + } + } + if (runtime_info.fs_info.addr_flags.front_face_ena) { + if (runtime_info.fs_info.en_flags.front_face_ena) { + ir.SetVectorReg(dst_vreg++, ir.GetAttributeU32(IR::Attribute::IsFrontFace)); + } else { + ir.SetVectorReg(dst_vreg++, ir.Imm32(0)); } - ++dst_vreg; } break; case Stage::Compute: diff --git a/src/shader_recompiler/runtime_info.h b/src/shader_recompiler/runtime_info.h index 4819027fc..4c779a368 100644 --- a/src/shader_recompiler/runtime_info.h +++ b/src/shader_recompiler/runtime_info.h @@ -7,6 +7,7 @@ #include #include #include "common/types.h" +#include "video_core/amdgpu/liverpool.h" #include "video_core/amdgpu/types.h" namespace Shader { @@ -96,16 +97,6 @@ enum class MrtSwizzle : u8 { }; static constexpr u32 MaxColorBuffers = 8; -enum class PsInputFlags : u8 { - None = 0, - PosX = 1 << 0, - PosY = 1 << 1, - PosZ = 1 << 2, - PosW = 1 << 3, - FrontFacing = 1 << 4, -}; -DECLARE_ENUM_FLAG_OPERATORS(PsInputFlags) - struct FragmentRuntimeInfo { struct PsInput { u8 param_index; @@ -115,8 +106,8 @@ struct FragmentRuntimeInfo { auto operator<=>(const PsInput&) const noexcept = default; }; - PsInputFlags en_flags; - PsInputFlags addr_flags; + AmdGpu::Liverpool::PsInput en_flags; + AmdGpu::Liverpool::PsInput addr_flags; u32 num_inputs; std::array inputs; struct PsColorBuffer { @@ -129,7 +120,7 @@ struct FragmentRuntimeInfo { bool operator==(const FragmentRuntimeInfo& other) const noexcept { return std::ranges::equal(color_buffers, other.color_buffers) && - en_flags == other.en_flags && addr_flags == other.addr_flags && + en_flags.raw == other.en_flags.raw && addr_flags.raw == other.addr_flags.raw && 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 60689f16f..ca3b01612 100644 --- a/src/video_core/amdgpu/liverpool.h +++ b/src/video_core/amdgpu/liverpool.h @@ -1071,23 +1071,26 @@ 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 PsInput { + u32 raw; + struct { + 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 { diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index b321aec82..25d811e8d 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -123,28 +123,8 @@ Shader::RuntimeInfo PipelineCache::BuildRuntimeInfo(Shader::Stage stage) { } case Shader::Stage::Fragment: { BuildCommon(regs.ps_program); - info.fs_info.en_flags = - (regs.ps_input_ena.pos_x_float_ena ? Shader::PsInputFlags::PosX - : Shader::PsInputFlags::None) | - (regs.ps_input_ena.pos_y_float_ena ? Shader::PsInputFlags::PosY - : Shader::PsInputFlags::None) | - (regs.ps_input_ena.pos_z_float_ena ? Shader::PsInputFlags::PosZ - : Shader::PsInputFlags::None) | - (regs.ps_input_ena.pos_w_float_ena ? Shader::PsInputFlags::PosW - : Shader::PsInputFlags::None) | - (regs.ps_input_ena.front_face_ena ? Shader::PsInputFlags::FrontFacing - : Shader::PsInputFlags::None); - info.fs_info.addr_flags = - (regs.ps_input_addr.pos_x_float_ena ? Shader::PsInputFlags::PosX - : Shader::PsInputFlags::None) | - (regs.ps_input_addr.pos_y_float_ena ? Shader::PsInputFlags::PosY - : Shader::PsInputFlags::None) | - (regs.ps_input_addr.pos_z_float_ena ? Shader::PsInputFlags::PosZ - : Shader::PsInputFlags::None) | - (regs.ps_input_addr.pos_w_float_ena ? Shader::PsInputFlags::PosW - : Shader::PsInputFlags::None) | - (regs.ps_input_addr.front_face_ena ? Shader::PsInputFlags::FrontFacing - : Shader::PsInputFlags::None); + info.fs_info.en_flags = regs.ps_input_ena; + info.fs_info.addr_flags = regs.ps_input_addr; const auto& ps_inputs = regs.ps_inputs; info.fs_info.num_inputs = regs.num_interp; for (u32 i = 0; i < regs.num_interp; i++) {