diff options
author | ReinUsesLisp <reinuseslisp@airmail.cc> | 2020-03-28 22:49:50 +0100 |
---|---|---|
committer | ReinUsesLisp <reinuseslisp@airmail.cc> | 2020-04-12 05:34:42 +0200 |
commit | 76f178ba6e7cc2925ffada341d1e14fb159e93c7 (patch) | |
tree | fec59062ca81807bd8ac4dc8e0216fe2f5c27384 /src/video_core/shader/decode | |
parent | shader_bytecode: Fix I2I_IMM encoding (diff) | |
download | yuzu-76f178ba6e7cc2925ffada341d1e14fb159e93c7.tar yuzu-76f178ba6e7cc2925ffada341d1e14fb159e93c7.tar.gz yuzu-76f178ba6e7cc2925ffada341d1e14fb159e93c7.tar.bz2 yuzu-76f178ba6e7cc2925ffada341d1e14fb159e93c7.tar.lz yuzu-76f178ba6e7cc2925ffada341d1e14fb159e93c7.tar.xz yuzu-76f178ba6e7cc2925ffada341d1e14fb159e93c7.tar.zst yuzu-76f178ba6e7cc2925ffada341d1e14fb159e93c7.zip |
Diffstat (limited to '')
-rw-r--r-- | src/video_core/shader/decode/video.cpp | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/src/video_core/shader/decode/video.cpp b/src/video_core/shader/decode/video.cpp index b047cf870..64ba60ea2 100644 --- a/src/video_core/shader/decode/video.cpp +++ b/src/video_core/shader/decode/video.cpp @@ -10,16 +10,24 @@ namespace VideoCommon::Shader { +using std::move; using Tegra::Shader::Instruction; using Tegra::Shader::OpCode; using Tegra::Shader::Pred; using Tegra::Shader::VideoType; using Tegra::Shader::VmadShr; +using Tegra::Shader::VmnmxOperation; +using Tegra::Shader::VmnmxType; u32 ShaderIR::DecodeVideo(NodeBlock& bb, u32 pc) { const Instruction instr = {program_code[pc]}; const auto opcode = OpCode::Decode(instr); + if (opcode->get().GetId() == OpCode::Id::VMNMX) { + DecodeVMNMX(bb, instr); + return pc; + } + const Node op_a = GetVideoOperand(GetRegister(instr.gpr8), instr.video.is_byte_chunk_a, instr.video.signed_a, instr.video.type_a, instr.video.byte_height_a); @@ -109,4 +117,54 @@ Node ShaderIR::GetVideoOperand(Node op, bool is_chunk, bool is_signed, } } +void ShaderIR::DecodeVMNMX(NodeBlock& bb, Tegra::Shader::Instruction instr) { + UNIMPLEMENTED_IF(!instr.vmnmx.is_op_b_register); + UNIMPLEMENTED_IF(instr.vmnmx.SourceFormatA() != VmnmxType::Bits32); + UNIMPLEMENTED_IF(instr.vmnmx.SourceFormatB() != VmnmxType::Bits32); + UNIMPLEMENTED_IF(instr.vmnmx.is_src_a_signed != instr.vmnmx.is_src_b_signed); + UNIMPLEMENTED_IF(instr.vmnmx.sat); + UNIMPLEMENTED_IF(instr.generates_cc); + + Node op_a = GetRegister(instr.gpr8); + Node op_b = GetRegister(instr.gpr20); + Node op_c = GetRegister(instr.gpr39); + + const bool is_oper1_signed = instr.vmnmx.is_src_a_signed; // Stubbed + const bool is_oper2_signed = instr.vmnmx.is_dest_signed; + + const auto operation_a = instr.vmnmx.mx ? OperationCode::IMax : OperationCode::IMin; + Node value = SignedOperation(operation_a, is_oper1_signed, move(op_a), move(op_b)); + + switch (instr.vmnmx.operation) { + case VmnmxOperation::Mrg_16H: + value = BitfieldInsert(move(op_c), move(value), 16, 16); + break; + case VmnmxOperation::Mrg_16L: + value = BitfieldInsert(move(op_c), move(value), 0, 16); + break; + case VmnmxOperation::Mrg_8B0: + value = BitfieldInsert(move(op_c), move(value), 0, 8); + break; + case VmnmxOperation::Mrg_8B2: + value = BitfieldInsert(move(op_c), move(value), 16, 8); + break; + case VmnmxOperation::Acc: + value = Operation(OperationCode::IAdd, move(value), move(op_c)); + break; + case VmnmxOperation::Min: + value = SignedOperation(OperationCode::IMin, is_oper2_signed, move(value), move(op_c)); + break; + case VmnmxOperation::Max: + value = SignedOperation(OperationCode::IMax, is_oper2_signed, move(value), move(op_c)); + break; + case VmnmxOperation::Nop: + break; + default: + UNREACHABLE(); + break; + } + + SetRegister(bb, instr.gpr0, move(value)); +} + } // namespace VideoCommon::Shader |