diff options
| author | 2019-05-19 14:02:58 -0400 | |
|---|---|---|
| committer | 2019-05-19 14:02:58 -0400 | |
| commit | d49efbfb4aa4e935f6c753871d6af6534701f542 (patch) | |
| tree | 79608391a32719a0be20c898fc79aba93f9f1d48 /src/video_core/shader/decode | |
| parent | Merge pull request #2410 from lioncash/affinity (diff) | |
| parent | shader_ir/other: Implement IPA.IDX (diff) | |
| download | yuzu-d49efbfb4aa4e935f6c753871d6af6534701f542.tar.gz yuzu-d49efbfb4aa4e935f6c753871d6af6534701f542.tar.xz yuzu-d49efbfb4aa4e935f6c753871d6af6534701f542.zip | |
Merge pull request #2441 from ReinUsesLisp/al2p
shader: Implement AL2P and ALD.PHYS
Diffstat (limited to 'src/video_core/shader/decode')
| -rw-r--r-- | src/video_core/shader/decode/memory.cpp | 30 | ||||
| -rw-r--r-- | src/video_core/shader/decode/other.cpp | 13 |
2 files changed, 33 insertions, 10 deletions
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp index ea1092db1..6a992c543 100644 --- a/src/video_core/shader/decode/memory.cpp +++ b/src/video_core/shader/decode/memory.cpp | |||
| @@ -12,6 +12,8 @@ | |||
| 12 | #include "video_core/engines/shader_bytecode.h" | 12 | #include "video_core/engines/shader_bytecode.h" |
| 13 | #include "video_core/shader/shader_ir.h" | 13 | #include "video_core/shader/shader_ir.h" |
| 14 | 14 | ||
| 15 | #pragma optimize("", off) | ||
| 16 | |||
| 15 | namespace VideoCommon::Shader { | 17 | namespace VideoCommon::Shader { |
| 16 | 18 | ||
| 17 | using Tegra::Shader::Attribute; | 19 | using Tegra::Shader::Attribute; |
| @@ -47,17 +49,20 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { | |||
| 47 | "Indirect attribute loads are not supported"); | 49 | "Indirect attribute loads are not supported"); |
| 48 | UNIMPLEMENTED_IF_MSG((instr.attribute.fmt20.immediate.Value() % sizeof(u32)) != 0, | 50 | UNIMPLEMENTED_IF_MSG((instr.attribute.fmt20.immediate.Value() % sizeof(u32)) != 0, |
| 49 | "Unaligned attribute loads are not supported"); | 51 | "Unaligned attribute loads are not supported"); |
| 52 | UNIMPLEMENTED_IF_MSG(instr.attribute.fmt20.IsPhysical() && | ||
| 53 | instr.attribute.fmt20.size != Tegra::Shader::AttributeSize::Word, | ||
| 54 | "Non-32 bits PHYS reads are not implemented"); | ||
| 50 | 55 | ||
| 51 | Tegra::Shader::IpaMode input_mode{Tegra::Shader::IpaInterpMode::Pass, | 56 | const Node buffer{GetRegister(instr.gpr39)}; |
| 52 | Tegra::Shader::IpaSampleMode::Default}; | ||
| 53 | 57 | ||
| 54 | u64 next_element = instr.attribute.fmt20.element; | 58 | u64 next_element = instr.attribute.fmt20.element; |
| 55 | auto next_index = static_cast<u64>(instr.attribute.fmt20.index.Value()); | 59 | auto next_index = static_cast<u64>(instr.attribute.fmt20.index.Value()); |
| 56 | 60 | ||
| 57 | const auto LoadNextElement = [&](u32 reg_offset) { | 61 | const auto LoadNextElement = [&](u32 reg_offset) { |
| 58 | const Node buffer = GetRegister(instr.gpr39); | 62 | const Node attribute{instr.attribute.fmt20.IsPhysical() |
| 59 | const Node attribute = GetInputAttribute(static_cast<Attribute::Index>(next_index), | 63 | ? GetPhysicalInputAttribute(instr.gpr8, buffer) |
| 60 | next_element, input_mode, buffer); | 64 | : GetInputAttribute(static_cast<Attribute::Index>(next_index), |
| 65 | next_element, buffer)}; | ||
| 61 | 66 | ||
| 62 | SetRegister(bb, instr.gpr0.Value() + reg_offset, attribute); | 67 | SetRegister(bb, instr.gpr0.Value() + reg_offset, attribute); |
| 63 | 68 | ||
| @@ -239,6 +244,21 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { | |||
| 239 | } | 244 | } |
| 240 | break; | 245 | break; |
| 241 | } | 246 | } |
| 247 | case OpCode::Id::AL2P: { | ||
| 248 | // Ignore al2p.direction since we don't care about it. | ||
| 249 | |||
| 250 | // Calculate emulation fake physical address. | ||
| 251 | const Node fixed_address{Immediate(static_cast<u32>(instr.al2p.address))}; | ||
| 252 | const Node reg{GetRegister(instr.gpr8)}; | ||
| 253 | const Node fake_address{Operation(OperationCode::IAdd, NO_PRECISE, reg, fixed_address)}; | ||
| 254 | |||
| 255 | // Set the fake address to target register. | ||
| 256 | SetRegister(bb, instr.gpr0, fake_address); | ||
| 257 | |||
| 258 | // Signal the shader IR to declare all possible attributes and varyings | ||
| 259 | uses_physical_attributes = true; | ||
| 260 | break; | ||
| 261 | } | ||
| 242 | default: | 262 | default: |
| 243 | UNIMPLEMENTED_MSG("Unhandled memory instruction: {}", opcode->get().GetName()); | 263 | UNIMPLEMENTED_MSG("Unhandled memory instruction: {}", opcode->get().GetName()); |
| 244 | } | 264 | } |
diff --git a/src/video_core/shader/decode/other.cpp b/src/video_core/shader/decode/other.cpp index d750a2936..fa17c45b5 100644 --- a/src/video_core/shader/decode/other.cpp +++ b/src/video_core/shader/decode/other.cpp | |||
| @@ -130,15 +130,18 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) { | |||
| 130 | break; | 130 | break; |
| 131 | } | 131 | } |
| 132 | case OpCode::Id::IPA: { | 132 | case OpCode::Id::IPA: { |
| 133 | const auto& attribute = instr.attribute.fmt28; | 133 | const bool is_physical = instr.ipa.idx && instr.gpr8.Value() != 0xff; |
| 134 | |||
| 135 | const auto attribute = instr.attribute.fmt28; | ||
| 134 | const Tegra::Shader::IpaMode input_mode{instr.ipa.interp_mode.Value(), | 136 | const Tegra::Shader::IpaMode input_mode{instr.ipa.interp_mode.Value(), |
| 135 | instr.ipa.sample_mode.Value()}; | 137 | instr.ipa.sample_mode.Value()}; |
| 136 | 138 | ||
| 137 | const Node attr = GetInputAttribute(attribute.index, attribute.element, input_mode); | 139 | Node value = is_physical ? GetPhysicalInputAttribute(instr.gpr8) |
| 138 | Node value = attr; | 140 | : GetInputAttribute(attribute.index, attribute.element); |
| 139 | const Tegra::Shader::Attribute::Index index = attribute.index.Value(); | 141 | const Tegra::Shader::Attribute::Index index = attribute.index.Value(); |
| 140 | if (index >= Tegra::Shader::Attribute::Index::Attribute_0 && | 142 | const bool is_generic = index >= Tegra::Shader::Attribute::Index::Attribute_0 && |
| 141 | index <= Tegra::Shader::Attribute::Index::Attribute_31) { | 143 | index <= Tegra::Shader::Attribute::Index::Attribute_31; |
| 144 | if (is_generic || is_physical) { | ||
| 142 | // TODO(Blinkhawk): There are cases where a perspective attribute use PASS. | 145 | // TODO(Blinkhawk): There are cases where a perspective attribute use PASS. |
| 143 | // In theory by setting them as perspective, OpenGL does the perspective correction. | 146 | // In theory by setting them as perspective, OpenGL does the perspective correction. |
| 144 | // A way must figured to reverse the last step of it. | 147 | // A way must figured to reverse the last step of it. |