diff options
| author | 2018-12-21 00:05:42 -0300 | |
|---|---|---|
| committer | 2019-01-15 17:54:50 -0300 | |
| commit | e3f1233ce13d82623173d690a6aa7819d68f069e (patch) | |
| tree | b2c02448aede72d7482c16c20f77e1e9e7864a42 /src | |
| parent | shader_decode: Implement FADD32I (diff) | |
| download | yuzu-e3f1233ce13d82623173d690a6aa7819d68f069e.tar.gz yuzu-e3f1233ce13d82623173d690a6aa7819d68f069e.tar.xz yuzu-e3f1233ce13d82623173d690a6aa7819d68f069e.zip | |
shader_decode: Implement LD_A
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/shader/decode/memory.cpp | 40 |
1 files changed, 39 insertions, 1 deletions
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp index d6086004b..30e2b33a3 100644 --- a/src/video_core/shader/decode/memory.cpp +++ b/src/video_core/shader/decode/memory.cpp | |||
| @@ -9,14 +9,52 @@ | |||
| 9 | 9 | ||
| 10 | namespace VideoCommon::Shader { | 10 | namespace VideoCommon::Shader { |
| 11 | 11 | ||
| 12 | using Tegra::Shader::Attribute; | ||
| 12 | using Tegra::Shader::Instruction; | 13 | using Tegra::Shader::Instruction; |
| 13 | using Tegra::Shader::OpCode; | 14 | using Tegra::Shader::OpCode; |
| 15 | using Tegra::Shader::Register; | ||
| 14 | 16 | ||
| 15 | u32 ShaderIR::DecodeMemory(BasicBlock& bb, u32 pc) { | 17 | u32 ShaderIR::DecodeMemory(BasicBlock& bb, u32 pc) { |
| 16 | const Instruction instr = {program_code[pc]}; | 18 | const Instruction instr = {program_code[pc]}; |
| 17 | const auto opcode = OpCode::Decode(instr); | 19 | const auto opcode = OpCode::Decode(instr); |
| 18 | 20 | ||
| 19 | UNIMPLEMENTED(); | 21 | switch (opcode->get().GetId()) { |
| 22 | case OpCode::Id::LD_A: { | ||
| 23 | // Note: Shouldn't this be interp mode flat? As in no interpolation made. | ||
| 24 | UNIMPLEMENTED_IF_MSG(instr.gpr8.Value() != Register::ZeroIndex, | ||
| 25 | "Indirect attribute loads are not supported"); | ||
| 26 | UNIMPLEMENTED_IF_MSG((instr.attribute.fmt20.immediate.Value() % sizeof(u32)) != 0, | ||
| 27 | "Unaligned attribute loads are not supported"); | ||
| 28 | |||
| 29 | Tegra::Shader::IpaMode input_mode{Tegra::Shader::IpaInterpMode::Perspective, | ||
| 30 | Tegra::Shader::IpaSampleMode::Default}; | ||
| 31 | |||
| 32 | u64 next_element = instr.attribute.fmt20.element; | ||
| 33 | auto next_index = static_cast<u64>(instr.attribute.fmt20.index.Value()); | ||
| 34 | |||
| 35 | const auto LoadNextElement = [&](u32 reg_offset) { | ||
| 36 | const Node buffer = GetRegister(instr.gpr39); | ||
| 37 | const Node attribute = GetInputAttribute(static_cast<Attribute::Index>(next_index), | ||
| 38 | next_element, input_mode, buffer); | ||
| 39 | |||
| 40 | SetRegister(bb, instr.gpr0.Value() + reg_offset, attribute); | ||
| 41 | |||
| 42 | // Load the next attribute element into the following register. If the element | ||
| 43 | // to load goes beyond the vec4 size, load the first element of the next | ||
| 44 | // attribute. | ||
| 45 | next_element = (next_element + 1) % 4; | ||
| 46 | next_index = next_index + (next_element == 0 ? 1 : 0); | ||
| 47 | }; | ||
| 48 | |||
| 49 | const u32 num_words = static_cast<u32>(instr.attribute.fmt20.size.Value()) + 1; | ||
| 50 | for (u32 reg_offset = 0; reg_offset < num_words; ++reg_offset) { | ||
| 51 | LoadNextElement(reg_offset); | ||
| 52 | } | ||
| 53 | break; | ||
| 54 | } | ||
| 55 | default: | ||
| 56 | UNIMPLEMENTED_MSG("Unhandled memory instruction: {}", opcode->get().GetName()); | ||
| 57 | } | ||
| 20 | 58 | ||
| 21 | return pc; | 59 | return pc; |
| 22 | } | 60 | } |