mirror of
				https://git.h3cjp.net/H3cJP/citra.git
				synced 2025-10-30 22:44:58 +00:00 
			
		
		
		
	Merge pull request #516 from Subv/f2i_r
GPU: Implemented the F2I_R shader instruction.
This commit is contained in:
		
						commit
						5fb99e6a16
					
				|  | @ -173,6 +173,13 @@ enum class SubOp : u64 { | |||
|     Min = 0x8, | ||||
| }; | ||||
| 
 | ||||
| enum class FloatRoundingOp : u64 { | ||||
|     None = 0, | ||||
|     Floor = 1, | ||||
|     Ceil = 2, | ||||
|     Trunc = 3, | ||||
| }; | ||||
| 
 | ||||
| union Instruction { | ||||
|     Instruction& operator=(const Instruction& instr) { | ||||
|         value = instr.value; | ||||
|  | @ -290,11 +297,20 @@ union Instruction { | |||
| 
 | ||||
|     union { | ||||
|         BitField<10, 2, Register::Size> size; | ||||
|         BitField<13, 1, u64> is_signed; | ||||
|         BitField<12, 1, u64> is_output_signed; | ||||
|         BitField<13, 1, u64> is_input_signed; | ||||
|         BitField<41, 2, u64> selector; | ||||
|         BitField<45, 1, u64> negate_a; | ||||
|         BitField<49, 1, u64> abs_a; | ||||
|         BitField<50, 1, u64> saturate_a; | ||||
| 
 | ||||
|         union { | ||||
|             BitField<39, 2, FloatRoundingOp> rounding; | ||||
|         } f2i; | ||||
| 
 | ||||
|         union { | ||||
|             BitField<39, 4, u64> rounding; | ||||
|         } f2f; | ||||
|     } conversion; | ||||
| 
 | ||||
|     union { | ||||
|  | @ -560,9 +576,9 @@ private: | |||
|             INST("0100110010101---", Id::F2F_C, Type::Conversion, "F2F_C"), | ||||
|             INST("0101110010101---", Id::F2F_R, Type::Conversion, "F2F_R"), | ||||
|             INST("0011100-10101---", Id::F2F_IMM, Type::Conversion, "F2F_IMM"), | ||||
|             INST("0100110010110---", Id::F2I_C, Type::Arithmetic, "F2I_C"), | ||||
|             INST("0101110010110---", Id::F2I_R, Type::Arithmetic, "F2I_R"), | ||||
|             INST("0011100-10110---", Id::F2I_IMM, Type::Arithmetic, "F2I_IMM"), | ||||
|             INST("0100110010110---", Id::F2I_C, Type::Conversion, "F2I_C"), | ||||
|             INST("0101110010110---", Id::F2I_R, Type::Conversion, "F2I_R"), | ||||
|             INST("0011100-10110---", Id::F2I_IMM, Type::Conversion, "F2I_IMM"), | ||||
|             INST("0100110010011---", Id::MOV_C, Type::Arithmetic, "MOV_C"), | ||||
|             INST("0101110010011---", Id::MOV_R, Type::Arithmetic, "MOV_R"), | ||||
|             INST("0011100-10011---", Id::MOV_IMM, Type::Arithmetic, "MOV_IMM"), | ||||
|  |  | |||
|  | @ -991,18 +991,20 @@ private: | |||
|                 ASSERT_MSG(!instr.conversion.selector, "Unimplemented"); | ||||
| 
 | ||||
|                 std::string op_a = | ||||
|                     regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_signed); | ||||
|                     regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_input_signed); | ||||
| 
 | ||||
|                 if (instr.conversion.abs_a) { | ||||
|                     op_a = "abs(" + op_a + ')'; | ||||
|                 } | ||||
| 
 | ||||
|                 regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_signed, 0, op_a, 1, 1); | ||||
|                 regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1, | ||||
|                                           1); | ||||
|                 break; | ||||
|             } | ||||
|             case OpCode::Id::I2F_R: { | ||||
|                 ASSERT_MSG(!instr.conversion.selector, "Unimplemented"); | ||||
|                 std::string op_a = | ||||
|                     regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_signed); | ||||
|                     regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_input_signed); | ||||
| 
 | ||||
|                 if (instr.conversion.abs_a) { | ||||
|                     op_a = "abs(" + op_a + ')'; | ||||
|  | @ -1012,6 +1014,8 @@ private: | |||
|                 break; | ||||
|             } | ||||
|             case OpCode::Id::F2F_R: { | ||||
|                 // TODO(Subv): Implement rounding operations.
 | ||||
|                 ASSERT_MSG(instr.conversion.f2f.rounding == 0, "Unimplemented rounding operation"); | ||||
|                 std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); | ||||
| 
 | ||||
|                 if (instr.conversion.abs_a) { | ||||
|  | @ -1021,6 +1025,43 @@ private: | |||
|                 regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1); | ||||
|                 break; | ||||
|             } | ||||
|             case OpCode::Id::F2I_R: { | ||||
|                 std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); | ||||
| 
 | ||||
|                 if (instr.conversion.abs_a) { | ||||
|                     op_a = "abs(" + op_a + ')'; | ||||
|                 } | ||||
| 
 | ||||
|                 using Tegra::Shader::FloatRoundingOp; | ||||
|                 switch (instr.conversion.f2i.rounding) { | ||||
|                 case FloatRoundingOp::None: | ||||
|                     break; | ||||
|                 case FloatRoundingOp::Floor: | ||||
|                     op_a = "floor(" + op_a + ')'; | ||||
|                     break; | ||||
|                 case FloatRoundingOp::Ceil: | ||||
|                     op_a = "ceil(" + op_a + ')'; | ||||
|                     break; | ||||
|                 case FloatRoundingOp::Trunc: | ||||
|                     op_a = "trunc(" + op_a + ')'; | ||||
|                     break; | ||||
|                 default: | ||||
|                     NGLOG_CRITICAL(HW_GPU, "Unimplemented f2i rounding mode {}", | ||||
|                                    static_cast<u32>(instr.conversion.f2i.rounding.Value())); | ||||
|                     UNREACHABLE(); | ||||
|                     break; | ||||
|                 } | ||||
| 
 | ||||
|                 if (instr.conversion.is_output_signed) { | ||||
|                     op_a = "int(" + op_a + ')'; | ||||
|                 } else { | ||||
|                     op_a = "uint(" + op_a + ')'; | ||||
|                 } | ||||
| 
 | ||||
|                 regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1, | ||||
|                                           1); | ||||
|                 break; | ||||
|             } | ||||
|             default: { | ||||
|                 NGLOG_CRITICAL(HW_GPU, "Unhandled conversion instruction: {}", opcode->GetName()); | ||||
|                 UNREACHABLE(); | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue