summaryrefslogtreecommitdiff
path: root/src/video_core/shader
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2020-04-01 21:37:32 -0300
committerGravatar ReinUsesLisp2020-04-01 21:48:55 -0300
commit2339fe199f3b08faa33b15048aa7158a2e0eff00 (patch)
tree28e28e8c22dfb27609f1926ea538a64dd4a6463f /src/video_core/shader
parentMerge pull request #3591 from ReinUsesLisp/vk-wrapper-part2 (diff)
downloadyuzu-2339fe199f3b08faa33b15048aa7158a2e0eff00.tar.gz
yuzu-2339fe199f3b08faa33b15048aa7158a2e0eff00.tar.xz
yuzu-2339fe199f3b08faa33b15048aa7158a2e0eff00.zip
shader_decompiler: Remove FragCoord.w hack and change IPA implementation
Credits go to gdkchan and Ryujinx. The pull request used for this can be found here: https://github.com/Ryujinx/Ryujinx/pull/1082 yuzu was already using the header for interpolation, but it was missing the FragCoord.w multiplication described in the linked pull request. This commit finally removes the FragCoord.w == 1.0f hack from the shader decompiler. While we are at it, this commit renames some enumerations to match Nvidia's documentation (linked below) and fixes component declaration order in the shader program header (z and w were swapped). https://github.com/NVIDIA/open-gpu-doc/blob/master/Shader-Program-Header/Shader-Program-Header.html
Diffstat (limited to 'src/video_core/shader')
-rw-r--r--src/video_core/shader/decode/other.cpp36
1 files changed, 21 insertions, 15 deletions
diff --git a/src/video_core/shader/decode/other.cpp b/src/video_core/shader/decode/other.cpp
index 4944e9d69..e6edec459 100644
--- a/src/video_core/shader/decode/other.cpp
+++ b/src/video_core/shader/decode/other.cpp
@@ -11,12 +11,17 @@
11 11
12namespace VideoCommon::Shader { 12namespace VideoCommon::Shader {
13 13
14using std::move;
14using Tegra::Shader::ConditionCode; 15using Tegra::Shader::ConditionCode;
15using Tegra::Shader::Instruction; 16using Tegra::Shader::Instruction;
17using Tegra::Shader::IpaInterpMode;
16using Tegra::Shader::OpCode; 18using Tegra::Shader::OpCode;
19using Tegra::Shader::PixelImap;
17using Tegra::Shader::Register; 20using Tegra::Shader::Register;
18using Tegra::Shader::SystemVariable; 21using Tegra::Shader::SystemVariable;
19 22
23using Index = Tegra::Shader::Attribute::Index;
24
20u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) { 25u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) {
21 const Instruction instr = {program_code[pc]}; 26 const Instruction instr = {program_code[pc]};
22 const auto opcode = OpCode::Decode(instr); 27 const auto opcode = OpCode::Decode(instr);
@@ -213,27 +218,28 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) {
213 } 218 }
214 case OpCode::Id::IPA: { 219 case OpCode::Id::IPA: {
215 const bool is_physical = instr.ipa.idx && instr.gpr8.Value() != 0xff; 220 const bool is_physical = instr.ipa.idx && instr.gpr8.Value() != 0xff;
216
217 const auto attribute = instr.attribute.fmt28; 221 const auto attribute = instr.attribute.fmt28;
218 const Tegra::Shader::IpaMode input_mode{instr.ipa.interp_mode.Value(), 222 const Index index = attribute.index;
219 instr.ipa.sample_mode.Value()};
220 223
221 Node value = is_physical ? GetPhysicalInputAttribute(instr.gpr8) 224 Node value = is_physical ? GetPhysicalInputAttribute(instr.gpr8)
222 : GetInputAttribute(attribute.index, attribute.element); 225 : GetInputAttribute(index, attribute.element);
223 const Tegra::Shader::Attribute::Index index = attribute.index.Value(); 226
224 const bool is_generic = index >= Tegra::Shader::Attribute::Index::Attribute_0 && 227 // Code taken from Ryujinx.
225 index <= Tegra::Shader::Attribute::Index::Attribute_31; 228 if (index >= Index::Attribute_0 && index <= Index::Attribute_31) {
226 if (is_generic || is_physical) { 229 const u32 location = static_cast<u32>(index) - static_cast<u32>(Index::Attribute_0);
227 // TODO(Blinkhawk): There are cases where a perspective attribute use PASS. 230 if (header.ps.GetPixelImap(location) == PixelImap::Perspective) {
228 // In theory by setting them as perspective, OpenGL does the perspective correction. 231 Node position_w = GetInputAttribute(Index::Position, 3);
229 // A way must figured to reverse the last step of it. 232 value = Operation(OperationCode::FMul, move(value), move(position_w));
230 if (input_mode.interpolation_mode == Tegra::Shader::IpaInterpMode::Multiply) {
231 value = Operation(OperationCode::FMul, PRECISE, value, GetRegister(instr.gpr20));
232 } 233 }
233 } 234 }
234 value = GetSaturatedFloat(value, instr.ipa.saturate);
235 235
236 SetRegister(bb, instr.gpr0, value); 236 if (instr.ipa.interp_mode == IpaInterpMode::Multiply) {
237 value = Operation(OperationCode::FMul, move(value), GetRegister(instr.gpr20));
238 }
239
240 value = GetSaturatedFloat(move(value), instr.ipa.saturate);
241
242 SetRegister(bb, instr.gpr0, move(value));
237 break; 243 break;
238 } 244 }
239 case OpCode::Id::OUT_R: { 245 case OpCode::Id::OUT_R: {