Merge pull request #3578 from ReinUsesLisp/vmnmx
shader/video: Partially implement VMNMX
This commit is contained in:
		| @@ -290,6 +290,23 @@ enum class VmadShr : u64 { | ||||
|     Shr15 = 2, | ||||
| }; | ||||
|  | ||||
| enum class VmnmxType : u64 { | ||||
|     Bits8, | ||||
|     Bits16, | ||||
|     Bits32, | ||||
| }; | ||||
|  | ||||
| enum class VmnmxOperation : u64 { | ||||
|     Mrg_16H = 0, | ||||
|     Mrg_16L = 1, | ||||
|     Mrg_8B0 = 2, | ||||
|     Mrg_8B2 = 3, | ||||
|     Acc = 4, | ||||
|     Min = 5, | ||||
|     Max = 6, | ||||
|     Nop = 7, | ||||
| }; | ||||
|  | ||||
| enum class XmadMode : u64 { | ||||
|     None = 0, | ||||
|     CLo = 1, | ||||
| @@ -1650,6 +1667,42 @@ union Instruction { | ||||
|         BitField<47, 1, u64> cc; | ||||
|     } vmad; | ||||
|  | ||||
|     union { | ||||
|         BitField<54, 1, u64> is_dest_signed; | ||||
|         BitField<48, 1, u64> is_src_a_signed; | ||||
|         BitField<49, 1, u64> is_src_b_signed; | ||||
|         BitField<37, 2, u64> src_format_a; | ||||
|         BitField<29, 2, u64> src_format_b; | ||||
|         BitField<56, 1, u64> mx; | ||||
|         BitField<55, 1, u64> sat; | ||||
|         BitField<36, 2, u64> selector_a; | ||||
|         BitField<28, 2, u64> selector_b; | ||||
|         BitField<50, 1, u64> is_op_b_register; | ||||
|         BitField<51, 3, VmnmxOperation> operation; | ||||
|  | ||||
|         VmnmxType SourceFormatA() const { | ||||
|             switch (src_format_a) { | ||||
|             case 0b11: | ||||
|                 return VmnmxType::Bits32; | ||||
|             case 0b10: | ||||
|                 return VmnmxType::Bits16; | ||||
|             default: | ||||
|                 return VmnmxType::Bits8; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         VmnmxType SourceFormatB() const { | ||||
|             switch (src_format_b) { | ||||
|             case 0b11: | ||||
|                 return VmnmxType::Bits32; | ||||
|             case 0b10: | ||||
|                 return VmnmxType::Bits16; | ||||
|             default: | ||||
|                 return VmnmxType::Bits8; | ||||
|             } | ||||
|         } | ||||
|     } vmnmx; | ||||
|  | ||||
|     union { | ||||
|         BitField<20, 16, u64> imm20_16; | ||||
|         BitField<35, 1, u64> high_b_rr; // used on RR | ||||
| @@ -1763,6 +1816,7 @@ public: | ||||
|         MEMBAR, | ||||
|         VMAD, | ||||
|         VSETP, | ||||
|         VMNMX, | ||||
|         FFMA_IMM, // Fused Multiply and Add | ||||
|         FFMA_CR, | ||||
|         FFMA_RC, | ||||
| @@ -2070,6 +2124,7 @@ private: | ||||
|             INST("1110111110011---", Id::MEMBAR, Type::Trivial, "MEMBAR"), | ||||
|             INST("01011111--------", Id::VMAD, Type::Video, "VMAD"), | ||||
|             INST("0101000011110---", Id::VSETP, Type::Video, "VSETP"), | ||||
|             INST("0011101---------", Id::VMNMX, Type::Video, "VMNMX"), | ||||
|             INST("0011001-1-------", Id::FFMA_IMM, Type::Ffma, "FFMA_IMM"), | ||||
|             INST("010010011-------", Id::FFMA_CR, Type::Ffma, "FFMA_CR"), | ||||
|             INST("010100011-------", Id::FFMA_RC, Type::Ffma, "FFMA_RC"), | ||||
| @@ -2170,7 +2225,7 @@ private: | ||||
|             INST("0011011-11111---", Id::SHF_LEFT_IMM, Type::Shift, "SHF_LEFT_IMM"), | ||||
|             INST("0100110011100---", Id::I2I_C, Type::Conversion, "I2I_C"), | ||||
|             INST("0101110011100---", Id::I2I_R, Type::Conversion, "I2I_R"), | ||||
|             INST("0011101-11100---", Id::I2I_IMM, Type::Conversion, "I2I_IMM"), | ||||
|             INST("0011100-11100---", Id::I2I_IMM, Type::Conversion, "I2I_IMM"), | ||||
|             INST("0100110010111---", Id::I2F_C, Type::Conversion, "I2F_C"), | ||||
|             INST("0101110010111---", Id::I2F_R, Type::Conversion, "I2F_R"), | ||||
|             INST("0011100-10111---", Id::I2F_IMM, Type::Conversion, "I2F_IMM"), | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -354,6 +354,9 @@ private: | ||||
|     /// Marks the usage of a input or output attribute. | ||||
|     void MarkAttributeUsage(Tegra::Shader::Attribute::Index index, u64 element); | ||||
|  | ||||
|     /// Decodes VMNMX instruction and inserts its code into the passed basic block. | ||||
|     void DecodeVMNMX(NodeBlock& bb, Tegra::Shader::Instruction instr); | ||||
|  | ||||
|     void WriteTexInstructionFloat(NodeBlock& bb, Tegra::Shader::Instruction instr, | ||||
|                                   const Node4& components); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user