forked from eden-emu/eden
		
	Merge pull request #3578 from ReinUsesLisp/vmnmx
shader/video: Partially implement VMNMX
This commit is contained in:
		
						commit
						1b20368a0a
					
				
					 3 changed files with 117 additions and 1 deletions
				
			
		|  | @ -290,6 +290,23 @@ enum class VmadShr : u64 { | ||||||
|     Shr15 = 2, |     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 { | enum class XmadMode : u64 { | ||||||
|     None = 0, |     None = 0, | ||||||
|     CLo = 1, |     CLo = 1, | ||||||
|  | @ -1650,6 +1667,42 @@ union Instruction { | ||||||
|         BitField<47, 1, u64> cc; |         BitField<47, 1, u64> cc; | ||||||
|     } vmad; |     } 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 { |     union { | ||||||
|         BitField<20, 16, u64> imm20_16; |         BitField<20, 16, u64> imm20_16; | ||||||
|         BitField<35, 1, u64> high_b_rr; // used on RR
 |         BitField<35, 1, u64> high_b_rr; // used on RR
 | ||||||
|  | @ -1763,6 +1816,7 @@ public: | ||||||
|         MEMBAR, |         MEMBAR, | ||||||
|         VMAD, |         VMAD, | ||||||
|         VSETP, |         VSETP, | ||||||
|  |         VMNMX, | ||||||
|         FFMA_IMM, // Fused Multiply and Add
 |         FFMA_IMM, // Fused Multiply and Add
 | ||||||
|         FFMA_CR, |         FFMA_CR, | ||||||
|         FFMA_RC, |         FFMA_RC, | ||||||
|  | @ -2070,6 +2124,7 @@ private: | ||||||
|             INST("1110111110011---", Id::MEMBAR, Type::Trivial, "MEMBAR"), |             INST("1110111110011---", Id::MEMBAR, Type::Trivial, "MEMBAR"), | ||||||
|             INST("01011111--------", Id::VMAD, Type::Video, "VMAD"), |             INST("01011111--------", Id::VMAD, Type::Video, "VMAD"), | ||||||
|             INST("0101000011110---", Id::VSETP, Type::Video, "VSETP"), |             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("0011001-1-------", Id::FFMA_IMM, Type::Ffma, "FFMA_IMM"), | ||||||
|             INST("010010011-------", Id::FFMA_CR, Type::Ffma, "FFMA_CR"), |             INST("010010011-------", Id::FFMA_CR, Type::Ffma, "FFMA_CR"), | ||||||
|             INST("010100011-------", Id::FFMA_RC, Type::Ffma, "FFMA_RC"), |             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("0011011-11111---", Id::SHF_LEFT_IMM, Type::Shift, "SHF_LEFT_IMM"), | ||||||
|             INST("0100110011100---", Id::I2I_C, Type::Conversion, "I2I_C"), |             INST("0100110011100---", Id::I2I_C, Type::Conversion, "I2I_C"), | ||||||
|             INST("0101110011100---", Id::I2I_R, Type::Conversion, "I2I_R"), |             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("0100110010111---", Id::I2F_C, Type::Conversion, "I2F_C"), | ||||||
|             INST("0101110010111---", Id::I2F_R, Type::Conversion, "I2F_R"), |             INST("0101110010111---", Id::I2F_R, Type::Conversion, "I2F_R"), | ||||||
|             INST("0011100-10111---", Id::I2F_IMM, Type::Conversion, "I2F_IMM"), |             INST("0011100-10111---", Id::I2F_IMM, Type::Conversion, "I2F_IMM"), | ||||||
|  |  | ||||||
|  | @ -10,16 +10,24 @@ | ||||||
| 
 | 
 | ||||||
| namespace VideoCommon::Shader { | namespace VideoCommon::Shader { | ||||||
| 
 | 
 | ||||||
|  | using std::move; | ||||||
| using Tegra::Shader::Instruction; | using Tegra::Shader::Instruction; | ||||||
| using Tegra::Shader::OpCode; | using Tegra::Shader::OpCode; | ||||||
| using Tegra::Shader::Pred; | using Tegra::Shader::Pred; | ||||||
| using Tegra::Shader::VideoType; | using Tegra::Shader::VideoType; | ||||||
| using Tegra::Shader::VmadShr; | using Tegra::Shader::VmadShr; | ||||||
|  | using Tegra::Shader::VmnmxOperation; | ||||||
|  | using Tegra::Shader::VmnmxType; | ||||||
| 
 | 
 | ||||||
| u32 ShaderIR::DecodeVideo(NodeBlock& bb, u32 pc) { | u32 ShaderIR::DecodeVideo(NodeBlock& bb, u32 pc) { | ||||||
|     const Instruction instr = {program_code[pc]}; |     const Instruction instr = {program_code[pc]}; | ||||||
|     const auto opcode = OpCode::Decode(instr); |     const auto opcode = OpCode::Decode(instr); | ||||||
| 
 | 
 | ||||||
|  |     if (opcode->get().GetId() == OpCode::Id::VMNMX) { | ||||||
|  |         DecodeVMNMX(bb, instr); | ||||||
|  |         return pc; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     const Node op_a = |     const Node op_a = | ||||||
|         GetVideoOperand(GetRegister(instr.gpr8), instr.video.is_byte_chunk_a, instr.video.signed_a, |         GetVideoOperand(GetRegister(instr.gpr8), instr.video.is_byte_chunk_a, instr.video.signed_a, | ||||||
|                         instr.video.type_a, instr.video.byte_height_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
 | } // namespace VideoCommon::Shader
 | ||||||
|  |  | ||||||
|  | @ -354,6 +354,9 @@ private: | ||||||
|     /// Marks the usage of a input or output attribute.
 |     /// Marks the usage of a input or output attribute.
 | ||||||
|     void MarkAttributeUsage(Tegra::Shader::Attribute::Index index, u64 element); |     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, |     void WriteTexInstructionFloat(NodeBlock& bb, Tegra::Shader::Instruction instr, | ||||||
|                                   const Node4& components); |                                   const Node4& components); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Fernando Sahmkow
						Fernando Sahmkow