diff options
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 55 | ||||
| -rw-r--r-- | src/video_core/shader/decode/video.cpp | 58 | ||||
| -rw-r--r-- | src/video_core/shader/shader_ir.h | 3 |
3 files changed, 116 insertions, 0 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index fcb2d7935..7400e1aa9 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -302,6 +302,23 @@ enum class VmadShr : u64 { | |||
| 302 | Shr15 = 2, | 302 | Shr15 = 2, |
| 303 | }; | 303 | }; |
| 304 | 304 | ||
| 305 | enum class VmnmxType : u64 { | ||
| 306 | Bits8, | ||
| 307 | Bits16, | ||
| 308 | Bits32, | ||
| 309 | }; | ||
| 310 | |||
| 311 | enum class VmnmxOperation : u64 { | ||
| 312 | Mrg_16H = 0, | ||
| 313 | Mrg_16L = 1, | ||
| 314 | Mrg_8B0 = 2, | ||
| 315 | Mrg_8B2 = 3, | ||
| 316 | Acc = 4, | ||
| 317 | Min = 5, | ||
| 318 | Max = 6, | ||
| 319 | Nop = 7, | ||
| 320 | }; | ||
| 321 | |||
| 305 | enum class XmadMode : u64 { | 322 | enum class XmadMode : u64 { |
| 306 | None = 0, | 323 | None = 0, |
| 307 | CLo = 1, | 324 | CLo = 1, |
| @@ -1663,6 +1680,42 @@ union Instruction { | |||
| 1663 | } vmad; | 1680 | } vmad; |
| 1664 | 1681 | ||
| 1665 | union { | 1682 | union { |
| 1683 | BitField<54, 1, u64> is_dest_signed; | ||
| 1684 | BitField<48, 1, u64> is_src_a_signed; | ||
| 1685 | BitField<49, 1, u64> is_src_b_signed; | ||
| 1686 | BitField<37, 2, u64> src_format_a; | ||
| 1687 | BitField<29, 2, u64> src_format_b; | ||
| 1688 | BitField<56, 1, u64> mx; | ||
| 1689 | BitField<55, 1, u64> sat; | ||
| 1690 | BitField<36, 2, u64> selector_a; | ||
| 1691 | BitField<28, 2, u64> selector_b; | ||
| 1692 | BitField<50, 1, u64> is_op_b_register; | ||
| 1693 | BitField<51, 3, VmnmxOperation> operation; | ||
| 1694 | |||
| 1695 | VmnmxType SourceFormatA() const { | ||
| 1696 | switch (src_format_a) { | ||
| 1697 | case 0b11: | ||
| 1698 | return VmnmxType::Bits32; | ||
| 1699 | case 0b10: | ||
| 1700 | return VmnmxType::Bits16; | ||
| 1701 | default: | ||
| 1702 | return VmnmxType::Bits8; | ||
| 1703 | } | ||
| 1704 | } | ||
| 1705 | |||
| 1706 | VmnmxType SourceFormatB() const { | ||
| 1707 | switch (src_format_b) { | ||
| 1708 | case 0b11: | ||
| 1709 | return VmnmxType::Bits32; | ||
| 1710 | case 0b10: | ||
| 1711 | return VmnmxType::Bits16; | ||
| 1712 | default: | ||
| 1713 | return VmnmxType::Bits8; | ||
| 1714 | } | ||
| 1715 | } | ||
| 1716 | } vmnmx; | ||
| 1717 | |||
| 1718 | union { | ||
| 1666 | BitField<20, 16, u64> imm20_16; | 1719 | BitField<20, 16, u64> imm20_16; |
| 1667 | BitField<35, 1, u64> high_b_rr; // used on RR | 1720 | BitField<35, 1, u64> high_b_rr; // used on RR |
| 1668 | BitField<36, 1, u64> product_shift_left; | 1721 | BitField<36, 1, u64> product_shift_left; |
| @@ -1773,6 +1826,7 @@ public: | |||
| 1773 | MEMBAR, | 1826 | MEMBAR, |
| 1774 | VMAD, | 1827 | VMAD, |
| 1775 | VSETP, | 1828 | VSETP, |
| 1829 | VMNMX, | ||
| 1776 | FFMA_IMM, // Fused Multiply and Add | 1830 | FFMA_IMM, // Fused Multiply and Add |
| 1777 | FFMA_CR, | 1831 | FFMA_CR, |
| 1778 | FFMA_RC, | 1832 | FFMA_RC, |
| @@ -2078,6 +2132,7 @@ private: | |||
| 2078 | INST("1110111110011---", Id::MEMBAR, Type::Trivial, "MEMBAR"), | 2132 | INST("1110111110011---", Id::MEMBAR, Type::Trivial, "MEMBAR"), |
| 2079 | INST("01011111--------", Id::VMAD, Type::Video, "VMAD"), | 2133 | INST("01011111--------", Id::VMAD, Type::Video, "VMAD"), |
| 2080 | INST("0101000011110---", Id::VSETP, Type::Video, "VSETP"), | 2134 | INST("0101000011110---", Id::VSETP, Type::Video, "VSETP"), |
| 2135 | INST("0011101---------", Id::VMNMX, Type::Video, "VMNMX"), | ||
| 2081 | INST("0011001-1-------", Id::FFMA_IMM, Type::Ffma, "FFMA_IMM"), | 2136 | INST("0011001-1-------", Id::FFMA_IMM, Type::Ffma, "FFMA_IMM"), |
| 2082 | INST("010010011-------", Id::FFMA_CR, Type::Ffma, "FFMA_CR"), | 2137 | INST("010010011-------", Id::FFMA_CR, Type::Ffma, "FFMA_CR"), |
| 2083 | INST("010100011-------", Id::FFMA_RC, Type::Ffma, "FFMA_RC"), | 2138 | INST("010100011-------", Id::FFMA_RC, Type::Ffma, "FFMA_RC"), |
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 @@ | |||
| 10 | 10 | ||
| 11 | namespace VideoCommon::Shader { | 11 | namespace VideoCommon::Shader { |
| 12 | 12 | ||
| 13 | using std::move; | ||
| 13 | using Tegra::Shader::Instruction; | 14 | using Tegra::Shader::Instruction; |
| 14 | using Tegra::Shader::OpCode; | 15 | using Tegra::Shader::OpCode; |
| 15 | using Tegra::Shader::Pred; | 16 | using Tegra::Shader::Pred; |
| 16 | using Tegra::Shader::VideoType; | 17 | using Tegra::Shader::VideoType; |
| 17 | using Tegra::Shader::VmadShr; | 18 | using Tegra::Shader::VmadShr; |
| 19 | using Tegra::Shader::VmnmxOperation; | ||
| 20 | using Tegra::Shader::VmnmxType; | ||
| 18 | 21 | ||
| 19 | u32 ShaderIR::DecodeVideo(NodeBlock& bb, u32 pc) { | 22 | u32 ShaderIR::DecodeVideo(NodeBlock& bb, u32 pc) { |
| 20 | const Instruction instr = {program_code[pc]}; | 23 | const Instruction instr = {program_code[pc]}; |
| 21 | const auto opcode = OpCode::Decode(instr); | 24 | const auto opcode = OpCode::Decode(instr); |
| 22 | 25 | ||
| 26 | if (opcode->get().GetId() == OpCode::Id::VMNMX) { | ||
| 27 | DecodeVMNMX(bb, instr); | ||
| 28 | return pc; | ||
| 29 | } | ||
| 30 | |||
| 23 | const Node op_a = | 31 | const Node op_a = |
| 24 | GetVideoOperand(GetRegister(instr.gpr8), instr.video.is_byte_chunk_a, instr.video.signed_a, | 32 | GetVideoOperand(GetRegister(instr.gpr8), instr.video.is_byte_chunk_a, instr.video.signed_a, |
| 25 | instr.video.type_a, instr.video.byte_height_a); | 33 | instr.video.type_a, instr.video.byte_height_a); |
| @@ -109,4 +117,54 @@ Node ShaderIR::GetVideoOperand(Node op, bool is_chunk, bool is_signed, | |||
| 109 | } | 117 | } |
| 110 | } | 118 | } |
| 111 | 119 | ||
| 120 | void ShaderIR::DecodeVMNMX(NodeBlock& bb, Tegra::Shader::Instruction instr) { | ||
| 121 | UNIMPLEMENTED_IF(!instr.vmnmx.is_op_b_register); | ||
| 122 | UNIMPLEMENTED_IF(instr.vmnmx.SourceFormatA() != VmnmxType::Bits32); | ||
| 123 | UNIMPLEMENTED_IF(instr.vmnmx.SourceFormatB() != VmnmxType::Bits32); | ||
| 124 | UNIMPLEMENTED_IF(instr.vmnmx.is_src_a_signed != instr.vmnmx.is_src_b_signed); | ||
| 125 | UNIMPLEMENTED_IF(instr.vmnmx.sat); | ||
| 126 | UNIMPLEMENTED_IF(instr.generates_cc); | ||
| 127 | |||
| 128 | Node op_a = GetRegister(instr.gpr8); | ||
| 129 | Node op_b = GetRegister(instr.gpr20); | ||
| 130 | Node op_c = GetRegister(instr.gpr39); | ||
| 131 | |||
| 132 | const bool is_oper1_signed = instr.vmnmx.is_src_a_signed; // Stubbed | ||
| 133 | const bool is_oper2_signed = instr.vmnmx.is_dest_signed; | ||
| 134 | |||
| 135 | const auto operation_a = instr.vmnmx.mx ? OperationCode::IMax : OperationCode::IMin; | ||
| 136 | Node value = SignedOperation(operation_a, is_oper1_signed, move(op_a), move(op_b)); | ||
| 137 | |||
| 138 | switch (instr.vmnmx.operation) { | ||
| 139 | case VmnmxOperation::Mrg_16H: | ||
| 140 | value = BitfieldInsert(move(op_c), move(value), 16, 16); | ||
| 141 | break; | ||
| 142 | case VmnmxOperation::Mrg_16L: | ||
| 143 | value = BitfieldInsert(move(op_c), move(value), 0, 16); | ||
| 144 | break; | ||
| 145 | case VmnmxOperation::Mrg_8B0: | ||
| 146 | value = BitfieldInsert(move(op_c), move(value), 0, 8); | ||
| 147 | break; | ||
| 148 | case VmnmxOperation::Mrg_8B2: | ||
| 149 | value = BitfieldInsert(move(op_c), move(value), 16, 8); | ||
| 150 | break; | ||
| 151 | case VmnmxOperation::Acc: | ||
| 152 | value = Operation(OperationCode::IAdd, move(value), move(op_c)); | ||
| 153 | break; | ||
| 154 | case VmnmxOperation::Min: | ||
| 155 | value = SignedOperation(OperationCode::IMin, is_oper2_signed, move(value), move(op_c)); | ||
| 156 | break; | ||
| 157 | case VmnmxOperation::Max: | ||
| 158 | value = SignedOperation(OperationCode::IMax, is_oper2_signed, move(value), move(op_c)); | ||
| 159 | break; | ||
| 160 | case VmnmxOperation::Nop: | ||
| 161 | break; | ||
| 162 | default: | ||
| 163 | UNREACHABLE(); | ||
| 164 | break; | ||
| 165 | } | ||
| 166 | |||
| 167 | SetRegister(bb, instr.gpr0, move(value)); | ||
| 168 | } | ||
| 169 | |||
| 112 | } // namespace VideoCommon::Shader | 170 | } // namespace VideoCommon::Shader |
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 80fc9b82c..0f1ebef1b 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h | |||
| @@ -350,6 +350,9 @@ private: | |||
| 350 | /// Marks the usage of a input or output attribute. | 350 | /// Marks the usage of a input or output attribute. |
| 351 | void MarkAttributeUsage(Tegra::Shader::Attribute::Index index, u64 element); | 351 | void MarkAttributeUsage(Tegra::Shader::Attribute::Index index, u64 element); |
| 352 | 352 | ||
| 353 | /// Decodes VMNMX instruction and inserts its code into the passed basic block. | ||
| 354 | void DecodeVMNMX(NodeBlock& bb, Tegra::Shader::Instruction instr); | ||
| 355 | |||
| 353 | void WriteTexInstructionFloat(NodeBlock& bb, Tegra::Shader::Instruction instr, | 356 | void WriteTexInstructionFloat(NodeBlock& bb, Tegra::Shader::Instruction instr, |
| 354 | const Node4& components); | 357 | const Node4& components); |
| 355 | 358 | ||