mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu.git
				synced 2025-05-12 00:45:25 +00:00 
			
		
		
		
	gl_shader_decompiler: Implement saturate for float instructions.
This commit is contained in:
		
							parent
							
								
									09b8a16414
								
							
						
					
					
						commit
						5f3d6c85db
					
				| @ -213,7 +213,6 @@ union Instruction { | |||||||
|     BitField<28, 8, Register> gpr28; |     BitField<28, 8, Register> gpr28; | ||||||
|     BitField<39, 8, Register> gpr39; |     BitField<39, 8, Register> gpr39; | ||||||
|     BitField<48, 16, u64> opcode; |     BitField<48, 16, u64> opcode; | ||||||
|     BitField<50, 1, u64> saturate_a; |  | ||||||
| 
 | 
 | ||||||
|     union { |     union { | ||||||
|         BitField<20, 19, u64> imm20_19; |         BitField<20, 19, u64> imm20_19; | ||||||
| @ -222,7 +221,7 @@ union Instruction { | |||||||
|         BitField<46, 1, u64> abs_a; |         BitField<46, 1, u64> abs_a; | ||||||
|         BitField<48, 1, u64> negate_a; |         BitField<48, 1, u64> negate_a; | ||||||
|         BitField<49, 1, u64> abs_b; |         BitField<49, 1, u64> abs_b; | ||||||
|         BitField<50, 1, u64> abs_d; |         BitField<50, 1, u64> saturate_d; | ||||||
|         BitField<56, 1, u64> negate_imm; |         BitField<56, 1, u64> negate_imm; | ||||||
| 
 | 
 | ||||||
|         union { |         union { | ||||||
|  | |||||||
| @ -299,13 +299,15 @@ public: | |||||||
|      * @param value The code representing the value to assign. |      * @param value The code representing the value to assign. | ||||||
|      * @param dest_num_components Number of components in the destination. |      * @param dest_num_components Number of components in the destination. | ||||||
|      * @param value_num_components Number of components in the value. |      * @param value_num_components Number of components in the value. | ||||||
|      * @param is_abs Optional, when True, applies absolute value to output. |      * @param is_saturated Optional, when True, saturates the provided value. | ||||||
|      * @param dest_elem Optional, the destination element to use for the operation. |      * @param dest_elem Optional, the destination element to use for the operation. | ||||||
|      */ |      */ | ||||||
|     void SetRegisterToFloat(const Register& reg, u64 elem, const std::string& value, |     void SetRegisterToFloat(const Register& reg, u64 elem, const std::string& value, | ||||||
|                             u64 dest_num_components, u64 value_num_components, bool is_abs = false, |                             u64 dest_num_components, u64 value_num_components, | ||||||
|                             u64 dest_elem = 0) { |                             bool is_saturated = false, u64 dest_elem = 0) { | ||||||
|         SetRegister(reg, elem, value, dest_num_components, value_num_components, is_abs, dest_elem); | 
 | ||||||
|  |         SetRegister(reg, elem, is_saturated ? "clamp(" + value + ", 0.0, 1.0)" : value, | ||||||
|  |                     dest_num_components, value_num_components, dest_elem); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
| @ -315,18 +317,21 @@ public: | |||||||
|      * @param value The code representing the value to assign. |      * @param value The code representing the value to assign. | ||||||
|      * @param dest_num_components Number of components in the destination. |      * @param dest_num_components Number of components in the destination. | ||||||
|      * @param value_num_components Number of components in the value. |      * @param value_num_components Number of components in the value. | ||||||
|      * @param is_abs Optional, when True, applies absolute value to output. |      * @param is_saturated Optional, when True, saturates the provided value. | ||||||
|      * @param dest_elem Optional, the destination element to use for the operation. |      * @param dest_elem Optional, the destination element to use for the operation. | ||||||
|      */ |      */ | ||||||
|     void SetRegisterToInteger(const Register& reg, bool is_signed, u64 elem, |     void SetRegisterToInteger(const Register& reg, bool is_signed, u64 elem, | ||||||
|                               const std::string& value, u64 dest_num_components, |                               const std::string& value, u64 dest_num_components, | ||||||
|                               u64 value_num_components, bool is_abs = false, u64 dest_elem = 0) { |                               u64 value_num_components, bool is_saturated = false, | ||||||
|  |                               u64 dest_elem = 0) { | ||||||
|  |         ASSERT_MSG(!is_saturated, "Unimplemented"); | ||||||
|  | 
 | ||||||
|         const std::string func = GetGLSLConversionFunc( |         const std::string func = GetGLSLConversionFunc( | ||||||
|             is_signed ? GLSLRegister::Type::Integer : GLSLRegister::Type::UnsignedInteger, |             is_signed ? GLSLRegister::Type::Integer : GLSLRegister::Type::UnsignedInteger, | ||||||
|             GLSLRegister::Type::Float); |             GLSLRegister::Type::Float); | ||||||
| 
 | 
 | ||||||
|         SetRegister(reg, elem, func + '(' + value + ')', dest_num_components, value_num_components, |         SetRegister(reg, elem, func + '(' + value + ')', dest_num_components, value_num_components, | ||||||
|                     is_abs, dest_elem); |                     dest_elem); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
| @ -500,12 +505,10 @@ private: | |||||||
|      * @param value The code representing the value to assign. |      * @param value The code representing the value to assign. | ||||||
|      * @param dest_num_components Number of components in the destination. |      * @param dest_num_components Number of components in the destination. | ||||||
|      * @param value_num_components Number of components in the value. |      * @param value_num_components Number of components in the value. | ||||||
|      * @param is_abs Optional, when True, applies absolute value to output. |  | ||||||
|      * @param dest_elem Optional, the destination element to use for the operation. |      * @param dest_elem Optional, the destination element to use for the operation. | ||||||
|      */ |      */ | ||||||
|     void SetRegister(const Register& reg, u64 elem, const std::string& value, |     void SetRegister(const Register& reg, u64 elem, const std::string& value, | ||||||
|                      u64 dest_num_components, u64 value_num_components, bool is_abs, |                      u64 dest_num_components, u64 value_num_components, u64 dest_elem) { | ||||||
|                      u64 dest_elem) { |  | ||||||
|         std::string dest = GetRegister(reg, dest_elem); |         std::string dest = GetRegister(reg, dest_elem); | ||||||
|         if (dest_num_components > 1) { |         if (dest_num_components > 1) { | ||||||
|             dest += GetSwizzle(elem); |             dest += GetSwizzle(elem); | ||||||
| @ -516,8 +519,6 @@ private: | |||||||
|             src += GetSwizzle(elem); |             src += GetSwizzle(elem); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         src = is_abs ? "abs(" + src + ')' : src; |  | ||||||
| 
 |  | ||||||
|         shader.AddLine(dest + " = " + src + ';'); |         shader.AddLine(dest + " = " + src + ';'); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -808,9 +809,8 @@ private: | |||||||
|             case OpCode::Id::FMUL_C: |             case OpCode::Id::FMUL_C: | ||||||
|             case OpCode::Id::FMUL_R: |             case OpCode::Id::FMUL_R: | ||||||
|             case OpCode::Id::FMUL_IMM: { |             case OpCode::Id::FMUL_IMM: { | ||||||
|                 ASSERT_MSG(!instr.saturate_a, "Unimplemented"); |                 regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " * " + op_b, 1, 1, | ||||||
| 
 |                                         instr.alu.saturate_d); | ||||||
|                 regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " * " + op_b, 1, 1, instr.alu.abs_d); |  | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|             case OpCode::Id::FMUL32_IMM: { |             case OpCode::Id::FMUL32_IMM: { | ||||||
| @ -823,41 +823,39 @@ private: | |||||||
|             case OpCode::Id::FADD_C: |             case OpCode::Id::FADD_C: | ||||||
|             case OpCode::Id::FADD_R: |             case OpCode::Id::FADD_R: | ||||||
|             case OpCode::Id::FADD_IMM: { |             case OpCode::Id::FADD_IMM: { | ||||||
|                 ASSERT_MSG(!instr.saturate_a, "Unimplemented"); |                 regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " + " + op_b, 1, 1, | ||||||
| 
 |                                         instr.alu.saturate_d); | ||||||
|                 regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " + " + op_b, 1, 1, instr.alu.abs_d); |  | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|             case OpCode::Id::MUFU: { |             case OpCode::Id::MUFU: { | ||||||
|                 ASSERT_MSG(!instr.saturate_a, "Unimplemented"); |  | ||||||
| 
 |  | ||||||
|                 switch (instr.sub_op) { |                 switch (instr.sub_op) { | ||||||
|                 case SubOp::Cos: |                 case SubOp::Cos: | ||||||
|                     regs.SetRegisterToFloat(instr.gpr0, 0, "cos(" + op_a + ')', 1, 1, |                     regs.SetRegisterToFloat(instr.gpr0, 0, "cos(" + op_a + ')', 1, 1, | ||||||
|                                             instr.alu.abs_d); |                                             instr.alu.saturate_d); | ||||||
|                     break; |                     break; | ||||||
|                 case SubOp::Sin: |                 case SubOp::Sin: | ||||||
|                     regs.SetRegisterToFloat(instr.gpr0, 0, "sin(" + op_a + ')', 1, 1, |                     regs.SetRegisterToFloat(instr.gpr0, 0, "sin(" + op_a + ')', 1, 1, | ||||||
|                                             instr.alu.abs_d); |                                             instr.alu.saturate_d); | ||||||
|                     break; |                     break; | ||||||
|                 case SubOp::Ex2: |                 case SubOp::Ex2: | ||||||
|                     regs.SetRegisterToFloat(instr.gpr0, 0, "exp2(" + op_a + ')', 1, 1, |                     regs.SetRegisterToFloat(instr.gpr0, 0, "exp2(" + op_a + ')', 1, 1, | ||||||
|                                             instr.alu.abs_d); |                                             instr.alu.saturate_d); | ||||||
|                     break; |                     break; | ||||||
|                 case SubOp::Lg2: |                 case SubOp::Lg2: | ||||||
|                     regs.SetRegisterToFloat(instr.gpr0, 0, "log2(" + op_a + ')', 1, 1, |                     regs.SetRegisterToFloat(instr.gpr0, 0, "log2(" + op_a + ')', 1, 1, | ||||||
|                                             instr.alu.abs_d); |                                             instr.alu.saturate_d); | ||||||
|                     break; |                     break; | ||||||
|                 case SubOp::Rcp: |                 case SubOp::Rcp: | ||||||
|                     regs.SetRegisterToFloat(instr.gpr0, 0, "1.0 / " + op_a, 1, 1, instr.alu.abs_d); |                     regs.SetRegisterToFloat(instr.gpr0, 0, "1.0 / " + op_a, 1, 1, | ||||||
|  |                                             instr.alu.saturate_d); | ||||||
|                     break; |                     break; | ||||||
|                 case SubOp::Rsq: |                 case SubOp::Rsq: | ||||||
|                     regs.SetRegisterToFloat(instr.gpr0, 0, "inversesqrt(" + op_a + ')', 1, 1, |                     regs.SetRegisterToFloat(instr.gpr0, 0, "inversesqrt(" + op_a + ')', 1, 1, | ||||||
|                                             instr.alu.abs_d); |                                             instr.alu.saturate_d); | ||||||
|                     break; |                     break; | ||||||
|                 case SubOp::Min: |                 case SubOp::Min: | ||||||
|                     regs.SetRegisterToFloat(instr.gpr0, 0, "min(" + op_a + "," + op_b + ')', 1, 1, |                     regs.SetRegisterToFloat(instr.gpr0, 0, "min(" + op_a + "," + op_b + ')', 1, 1, | ||||||
|                                             instr.alu.abs_d); |                                             instr.alu.saturate_d); | ||||||
|                     break; |                     break; | ||||||
|                 default: |                 default: | ||||||
|                     NGLOG_CRITICAL(HW_GPU, "Unhandled MUFU sub op: {0:x}", |                     NGLOG_CRITICAL(HW_GPU, "Unhandled MUFU sub op: {0:x}", | ||||||
| @ -1028,8 +1026,8 @@ private: | |||||||
|             case OpCode::Id::IADD_C: |             case OpCode::Id::IADD_C: | ||||||
|             case OpCode::Id::IADD_R: |             case OpCode::Id::IADD_R: | ||||||
|             case OpCode::Id::IADD_IMM: { |             case OpCode::Id::IADD_IMM: { | ||||||
|                 ASSERT_MSG(!instr.saturate_a, "Unimplemented"); |                 regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " + " + op_b, 1, 1, | ||||||
|                 regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " + " + op_b, 1, 1); |                                           instr.alu.saturate_d); | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|             case OpCode::Id::ISCADD_C: |             case OpCode::Id::ISCADD_C: | ||||||
| @ -1051,8 +1049,6 @@ private: | |||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         case OpCode::Type::Ffma: { |         case OpCode::Type::Ffma: { | ||||||
|             ASSERT_MSG(!instr.saturate_a, "Unimplemented"); |  | ||||||
| 
 |  | ||||||
|             std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); |             std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); | ||||||
|             std::string op_b = instr.ffma.negate_b ? "-" : ""; |             std::string op_b = instr.ffma.negate_b ? "-" : ""; | ||||||
|             std::string op_c = instr.ffma.negate_c ? "-" : ""; |             std::string op_c = instr.ffma.negate_c ? "-" : ""; | ||||||
| @ -1086,13 +1082,13 @@ private: | |||||||
|             } |             } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " * " + op_b + " + " + op_c, 1, 1); |             regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " * " + op_b + " + " + op_c, 1, 1, | ||||||
|  |                                     instr.alu.saturate_d); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         case OpCode::Type::Conversion: { |         case OpCode::Type::Conversion: { | ||||||
|             ASSERT_MSG(instr.conversion.size == Register::Size::Word, "Unimplemented"); |             ASSERT_MSG(instr.conversion.size == Register::Size::Word, "Unimplemented"); | ||||||
|             ASSERT_MSG(!instr.conversion.negate_a, "Unimplemented"); |             ASSERT_MSG(!instr.conversion.negate_a, "Unimplemented"); | ||||||
|             ASSERT_MSG(!instr.saturate_a, "Unimplemented"); |  | ||||||
| 
 | 
 | ||||||
|             switch (opcode->GetId()) { |             switch (opcode->GetId()) { | ||||||
|             case OpCode::Id::I2I_R: { |             case OpCode::Id::I2I_R: { | ||||||
| @ -1106,7 +1102,7 @@ private: | |||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1, |                 regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1, | ||||||
|                                           1); |                                           1, instr.alu.saturate_d); | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|             case OpCode::Id::I2F_R: { |             case OpCode::Id::I2F_R: { | ||||||
| @ -1122,8 +1118,6 @@ private: | |||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|             case OpCode::Id::F2F_R: { |             case OpCode::Id::F2F_R: { | ||||||
|                 ASSERT_MSG(!instr.saturate_a, "Unimplemented"); |  | ||||||
| 
 |  | ||||||
|                 std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); |                 std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); | ||||||
| 
 | 
 | ||||||
|                 switch (instr.conversion.f2f.rounding) { |                 switch (instr.conversion.f2f.rounding) { | ||||||
| @ -1149,7 +1143,7 @@ private: | |||||||
|                     op_a = "abs(" + op_a + ')'; |                     op_a = "abs(" + op_a + ')'; | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1); |                 regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1, instr.alu.saturate_d); | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|             case OpCode::Id::F2I_R: { |             case OpCode::Id::F2I_R: { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 bunnei
						bunnei