mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu.git
				synced 2025-05-12 00:45:25 +00:00 
			
		
		
		
	Merge pull request #416 from bunnei/shader-ints-p3
gl_shader_decompiler: Implement MOV32I, partially implement I2I, I2F
This commit is contained in:
		
						commit
						6c464a2a4a
					
				| @ -25,6 +25,13 @@ struct Register { | ||||
|     /// Register 255 is special cased to always be 0
 | ||||
|     static constexpr size_t ZeroIndex = 255; | ||||
| 
 | ||||
|     enum class Size : u64 { | ||||
|         Byte = 0, | ||||
|         Short = 1, | ||||
|         Word = 2, | ||||
|         Long = 3, | ||||
|     }; | ||||
| 
 | ||||
|     constexpr Register() = default; | ||||
| 
 | ||||
|     constexpr Register(u64 value) : value(value) {} | ||||
| @ -236,6 +243,15 @@ union Instruction { | ||||
|         BitField<56, 1, u64> neg_imm; | ||||
|     } fset; | ||||
| 
 | ||||
|     union { | ||||
|         BitField<10, 2, Register::Size> size; | ||||
|         BitField<13, 1, u64> is_signed; | ||||
|         BitField<41, 2, u64> selector; | ||||
|         BitField<45, 1, u64> negate_a; | ||||
|         BitField<49, 1, u64> abs_a; | ||||
|         BitField<50, 1, u64> saturate_a; | ||||
|     } conversion; | ||||
| 
 | ||||
|     BitField<61, 1, u64> is_b_imm; | ||||
|     BitField<60, 1, u64> is_b_gpr; | ||||
|     BitField<59, 1, u64> is_c_gpr; | ||||
| @ -290,7 +306,7 @@ public: | ||||
|         MOV_C, | ||||
|         MOV_R, | ||||
|         MOV_IMM, | ||||
|         MOV32I, | ||||
|         MOV32_IMM, | ||||
|         SHR_C, | ||||
|         SHR_R, | ||||
|         SHR_IMM, | ||||
| @ -314,6 +330,7 @@ public: | ||||
|         FloatSet, | ||||
|         FloatSetPredicate, | ||||
|         IntegerSetPredicate, | ||||
|         Conversion, | ||||
|         Unknown, | ||||
|     }; | ||||
| 
 | ||||
| @ -435,20 +452,20 @@ private: | ||||
|             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("0100110010111---", Id::I2F_C, Type::Arithmetic, "I2F_C"), | ||||
|             INST("0101110010111---", Id::I2F_R, Type::Arithmetic, "I2F_R"), | ||||
|             INST("0011100-10111---", Id::I2F_IMM, Type::Arithmetic, "I2F_IMM"), | ||||
|             INST("0100110011100---", Id::I2I_C, Type::Arithmetic, "I2I_C"), | ||||
|             INST("0101110011100---", Id::I2I_R, Type::Arithmetic, "I2I_R"), | ||||
|             INST("01110001-1000---", Id::I2I_IMM, Type::Arithmetic, "I2I_IMM"), | ||||
|             INST("000001----------", Id::LOP32I, Type::Arithmetic, "LOP32I"), | ||||
|             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"), | ||||
|             INST("000000010000----", Id::MOV32I, Type::Arithmetic, "MOV32I"), | ||||
|             INST("000000010000----", Id::MOV32_IMM, Type::Arithmetic, "MOV32_IMM"), | ||||
|             INST("0100110000101---", Id::SHR_C, Type::Arithmetic, "SHR_C"), | ||||
|             INST("0101110000101---", Id::SHR_R, Type::Arithmetic, "SHR_R"), | ||||
|             INST("0011100-00101---", Id::SHR_IMM, Type::Arithmetic, "SHR_IMM"), | ||||
|             INST("0100110011100---", Id::I2I_C, Type::Conversion, "I2I_C"), | ||||
|             INST("0101110011100---", Id::I2I_R, Type::Conversion, "I2I_R"), | ||||
|             INST("01110001-1000---", 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"), | ||||
|             INST("01011000--------", Id::FSET_R, Type::FloatSet, "FSET_R"), | ||||
|             INST("0100100---------", Id::FSET_C, Type::FloatSet, "FSET_C"), | ||||
|             INST("0011000---------", Id::FSET_IMM, Type::FloatSet, "FSET_IMM"), | ||||
|  | ||||
| @ -153,85 +153,61 @@ private: | ||||
|  */ | ||||
| class GLSLRegister { | ||||
| public: | ||||
|     GLSLRegister(size_t index, ShaderWriter& shader) | ||||
|         : index{index}, shader{shader}, float_str{"freg_" + std::to_string(index)}, | ||||
|           integer_str{"ireg_" + std::to_string(index)} {} | ||||
|     enum class Type { | ||||
|         Float, | ||||
|         Integer, | ||||
|         UnsignedInteger, | ||||
|     }; | ||||
| 
 | ||||
|     /// Returns a GLSL string representing the current state of the register
 | ||||
|     const std::string& GetActiveString() { | ||||
|         declr_type.insert(active_type); | ||||
|     GLSLRegister(size_t index, ShaderWriter& shader) : index{index}, shader{shader} {} | ||||
| 
 | ||||
|         switch (active_type) { | ||||
|     /// Gets the GLSL type string for a register
 | ||||
|     static std::string GetTypeString(Type type) { | ||||
|         switch (type) { | ||||
|         case Type::Float: | ||||
|             return float_str; | ||||
|             return "float"; | ||||
|         case Type::Integer: | ||||
|             return integer_str; | ||||
|             return "int"; | ||||
|         case Type::UnsignedInteger: | ||||
|             return "uint"; | ||||
|         } | ||||
| 
 | ||||
|         UNREACHABLE(); | ||||
|         return float_str; | ||||
|         return {}; | ||||
|     } | ||||
| 
 | ||||
|     /// Returns a GLSL string representing the register as a float
 | ||||
|     const std::string& GetFloatString() const { | ||||
|         ASSERT(IsFloatUsed()); | ||||
|         return float_str; | ||||
|     /// Gets the GLSL register prefix string, used for declarations and referencing
 | ||||
|     static std::string GetPrefixString(Type type) { | ||||
|         return "reg_" + GetTypeString(type) + '_'; | ||||
|     } | ||||
| 
 | ||||
|     /// Returns a GLSL string representing the register as an integer
 | ||||
|     const std::string& GetIntegerString() const { | ||||
|         ASSERT(IsIntegerUsed()); | ||||
|         return integer_str; | ||||
|     /// Returns a GLSL string representing the current state of the register
 | ||||
|     const std::string GetActiveString() { | ||||
|         declr_type.insert(active_type); | ||||
|         return GetPrefixString(active_type) + std::to_string(index); | ||||
|     } | ||||
| 
 | ||||
|     /// Convert the current register state from float to integer
 | ||||
|     void FloatToInteger() { | ||||
|         ASSERT(active_type == Type::Float); | ||||
| 
 | ||||
|         const std::string src = GetActiveString(); | ||||
|         active_type = Type::Integer; | ||||
|         const std::string dest = GetActiveString(); | ||||
| 
 | ||||
|         shader.AddLine(dest + " = floatBitsToInt(" + src + ");"); | ||||
|     } | ||||
| 
 | ||||
|     /// Convert the current register state from integer to float
 | ||||
|     void IntegerToFloat() { | ||||
|         ASSERT(active_type == Type::Integer); | ||||
| 
 | ||||
|         const std::string src = GetActiveString(); | ||||
|         active_type = Type::Float; | ||||
|         const std::string dest = GetActiveString(); | ||||
| 
 | ||||
|         shader.AddLine(dest + " = intBitsToFloat(" + src + ");"); | ||||
|     } | ||||
| 
 | ||||
|     /// Returns true if the register was ever used as a float, used for register declarations
 | ||||
|     bool IsFloatUsed() const { | ||||
|         return declr_type.find(Type::Float) != declr_type.end(); | ||||
|     } | ||||
| 
 | ||||
|     /// Returns true if the register was ever used as an integer, used for register declarations
 | ||||
|     bool IsIntegerUsed() const { | ||||
|         return declr_type.find(Type::Integer) != declr_type.end(); | ||||
|     } | ||||
| 
 | ||||
|     /// Returns true if the active type is float
 | ||||
|     /// Returns true if the active type is a float
 | ||||
|     bool IsFloat() const { | ||||
|         return active_type == Type::Float; | ||||
|     } | ||||
| 
 | ||||
|     /// Returns true if the active type is integer
 | ||||
|     /// Returns true if the active type is an integer
 | ||||
|     bool IsInteger() const { | ||||
|         return active_type == Type::Integer; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     enum class Type { | ||||
|         Float, | ||||
|         Integer, | ||||
|     }; | ||||
|     /// Returns the index of the register
 | ||||
|     size_t GetIndex() const { | ||||
|         return index; | ||||
|     } | ||||
| 
 | ||||
|     /// Returns a set of the declared types of the register
 | ||||
|     const std::set<Type>& DeclaredTypes() const { | ||||
|         return declr_type; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     const size_t index; | ||||
|     const std::string float_str; | ||||
|     const std::string integer_str; | ||||
| @ -254,18 +230,35 @@ public: | ||||
|         BuildRegisterList(); | ||||
|     } | ||||
| 
 | ||||
|     /// Generates code representing a temporary (GPR) register.
 | ||||
|     std::string GetRegister(const Register& reg, unsigned elem = 0) { | ||||
|         if (reg == Register::ZeroIndex) { | ||||
|             return "0"; | ||||
|         } | ||||
| 
 | ||||
|         return regs[reg.GetSwizzledIndex(elem)].GetActiveString(); | ||||
|     /**
 | ||||
|      * Gets a register as an float. | ||||
|      * @param reg The register to get. | ||||
|      * @param elem The element to use for the operation. | ||||
|      * @returns GLSL string corresponding to the register as a float. | ||||
|      */ | ||||
|     std::string GetRegisterAsFloat(const Register& reg, unsigned elem = 0) { | ||||
|         ASSERT(regs[reg].IsFloat()); | ||||
|         return GetRegister(reg, elem); | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * Writes code that does a register assignment to float value operation. Should only be used | ||||
|      * with shader instructions that deal with floats. | ||||
|      * Gets a register as an integer. | ||||
|      * @param reg The register to get. | ||||
|      * @param elem The element to use for the operation. | ||||
|      * @param is_signed Whether to get the register as a signed (or unsigned) integer. | ||||
|      * @returns GLSL string corresponding to the register as an integer. | ||||
|      */ | ||||
|     std::string GetRegisterAsInteger(const Register& reg, unsigned elem = 0, | ||||
|                                      bool is_signed = true) { | ||||
|         const std::string func = GetGLSLConversionFunc( | ||||
|             GLSLRegister::Type::Float, | ||||
|             is_signed ? GLSLRegister::Type::Integer : GLSLRegister::Type::UnsignedInteger); | ||||
| 
 | ||||
|         return func + '(' + GetRegister(reg, elem) + ')'; | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * Writes code that does a register assignment to float value operation. | ||||
|      * @param reg The destination register to use. | ||||
|      * @param elem The element to use for the operation. | ||||
|      * @param value The code representing the value to assign. | ||||
| @ -277,21 +270,28 @@ public: | ||||
|     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_elem = 0) { | ||||
|         ASSERT(regs[reg].IsFloat()); | ||||
|         SetRegister(reg, elem, value, dest_num_components, value_num_components, is_abs, dest_elem); | ||||
|     } | ||||
| 
 | ||||
|         std::string dest = GetRegister(reg, dest_elem); | ||||
|         if (dest_num_components > 1) { | ||||
|             dest += GetSwizzle(elem); | ||||
|         } | ||||
|     /**
 | ||||
|      * Writes code that does a register assignment to integer value operation. | ||||
|      * @param reg The destination register to use. | ||||
|      * @param elem The element to use for the operation. | ||||
|      * @param value The code representing the value to assign. | ||||
|      * @param dest_num_components Number of components in the destination. | ||||
|      * @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. | ||||
|      */ | ||||
|     void SetRegisterToInteger(const Register& reg, bool is_signed, u64 elem, | ||||
|                               const std::string& value, u64 dest_num_components, | ||||
|                               u64 value_num_components, bool is_abs = false, u64 dest_elem = 0) { | ||||
|         const std::string func = GetGLSLConversionFunc( | ||||
|             is_signed ? GLSLRegister::Type::Integer : GLSLRegister::Type::UnsignedInteger, | ||||
|             GLSLRegister::Type::Float); | ||||
| 
 | ||||
|         std::string src = '(' + value + ')'; | ||||
|         if (value_num_components > 1) { | ||||
|             src += GetSwizzle(elem); | ||||
|         } | ||||
| 
 | ||||
|         src = is_abs ? "abs(" + src + ')' : src; | ||||
| 
 | ||||
|         shader.AddLine(dest + " = " + src + ';'); | ||||
|         SetRegister(reg, elem, func + '(' + value + ')', dest_num_components, value_num_components, | ||||
|                     is_abs, dest_elem); | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
| @ -302,7 +302,7 @@ public: | ||||
|      * @param attribute The input attibute to use as the source value. | ||||
|      */ | ||||
|     void SetRegisterToInputAttibute(const Register& reg, u64 elem, Attribute::Index attribute) { | ||||
|         std::string dest = GetRegister(reg); | ||||
|         std::string dest = GetRegisterAsFloat(reg); | ||||
|         std::string src = GetInputAttribute(attribute) + GetSwizzle(elem); | ||||
| 
 | ||||
|         if (regs[reg].IsFloat()) { | ||||
| @ -323,7 +323,7 @@ public: | ||||
|      */ | ||||
|     void SetOutputAttributeToRegister(Attribute::Index attribute, u64 elem, const Register& reg) { | ||||
|         std::string dest = GetOutputAttribute(attribute) + GetSwizzle(elem); | ||||
|         std::string src = GetRegister(reg); | ||||
|         std::string src = GetRegisterAsFloat(reg); | ||||
|         ASSERT_MSG(regs[reg].IsFloat(), "Output attributes must be set to a float"); | ||||
|         shader.AddLine(dest + " = " + src + ';'); | ||||
|     } | ||||
| @ -347,11 +347,10 @@ public: | ||||
|     /// Add declarations for registers
 | ||||
|     void GenerateDeclarations() { | ||||
|         for (const auto& reg : regs) { | ||||
|             if (reg.IsFloatUsed()) { | ||||
|                 declarations.AddLine("float " + reg.GetFloatString() + " = 0.0;"); | ||||
|             } | ||||
|             if (reg.IsIntegerUsed()) { | ||||
|                 declarations.AddLine("int " + reg.GetIntegerString() + " = 0;"); | ||||
|             for (const auto& type : reg.DeclaredTypes()) { | ||||
|                 declarations.AddLine(GLSLRegister::GetTypeString(type) + ' ' + | ||||
|                                      GLSLRegister::GetPrefixString(type) + | ||||
|                                      std::to_string(reg.GetIndex()) + " = 0;"); | ||||
|             } | ||||
|         } | ||||
|         declarations.AddNewLine(); | ||||
| @ -395,6 +394,51 @@ public: | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     /// Build GLSL conversion function, e.g. floatBitsToInt, intBitsToFloat, etc.
 | ||||
|     const std::string GetGLSLConversionFunc(GLSLRegister::Type src, GLSLRegister::Type dest) const { | ||||
|         const std::string src_type = GLSLRegister::GetTypeString(src); | ||||
|         std::string dest_type = GLSLRegister::GetTypeString(dest); | ||||
|         dest_type[0] = toupper(dest_type[0]); | ||||
|         return src_type + "BitsTo" + dest_type; | ||||
|     } | ||||
| 
 | ||||
|     /// Generates code representing a temporary (GPR) register.
 | ||||
|     std::string GetRegister(const Register& reg, unsigned elem) { | ||||
|         if (reg == Register::ZeroIndex) { | ||||
|             return "0"; | ||||
|         } | ||||
| 
 | ||||
|         return regs[reg.GetSwizzledIndex(elem)].GetActiveString(); | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * Writes code that does a register assignment to value operation. | ||||
|      * @param reg The destination register to use. | ||||
|      * @param elem The element to use for the operation. | ||||
|      * @param value The code representing the value to assign. | ||||
|      * @param dest_num_components Number of components in the destination. | ||||
|      * @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. | ||||
|      */ | ||||
|     void SetRegister(const Register& reg, u64 elem, const std::string& value, | ||||
|                      u64 dest_num_components, u64 value_num_components, bool is_abs, | ||||
|                      u64 dest_elem) { | ||||
|         std::string dest = GetRegister(reg, dest_elem); | ||||
|         if (dest_num_components > 1) { | ||||
|             dest += GetSwizzle(elem); | ||||
|         } | ||||
| 
 | ||||
|         std::string src = '(' + value + ')'; | ||||
|         if (value_num_components > 1) { | ||||
|             src += GetSwizzle(elem); | ||||
|         } | ||||
| 
 | ||||
|         src = is_abs ? "abs(" + src + ')' : src; | ||||
| 
 | ||||
|         shader.AddLine(dest + " = " + src + ';'); | ||||
|     } | ||||
| 
 | ||||
|     /// Build the GLSL register list.
 | ||||
|     void BuildRegisterList() { | ||||
|         for (size_t index = 0; index < Register::NumRegisters; ++index) { | ||||
| @ -598,7 +642,7 @@ private: | ||||
|         switch (opcode->GetType()) { | ||||
|         case OpCode::Type::Arithmetic: { | ||||
|             std::string op_a = instr.alu.negate_a ? "-" : ""; | ||||
|             op_a += regs.GetRegister(instr.gpr8); | ||||
|             op_a += regs.GetRegisterAsFloat(instr.gpr8); | ||||
|             if (instr.alu.abs_a) { | ||||
|                 op_a = "abs(" + op_a + ')'; | ||||
|             } | ||||
| @ -609,7 +653,7 @@ private: | ||||
|                 op_b += GetImmediate19(instr); | ||||
|             } else { | ||||
|                 if (instr.is_b_gpr) { | ||||
|                     op_b += regs.GetRegister(instr.gpr20); | ||||
|                     op_b += regs.GetRegisterAsFloat(instr.gpr20); | ||||
|                 } else { | ||||
|                     op_b += regs.GetUniform(instr.uniform, instr.gpr0); | ||||
|                 } | ||||
| @ -620,6 +664,11 @@ private: | ||||
|             } | ||||
| 
 | ||||
|             switch (opcode->GetId()) { | ||||
|             case OpCode::Id::MOV32_IMM: { | ||||
|                 // mov32i doesn't have abs or neg bits.
 | ||||
|                 regs.SetRegisterToFloat(instr.gpr0, 0, GetImmediate32(instr), 1, 1); | ||||
|                 break; | ||||
|             } | ||||
|             case OpCode::Id::FMUL_C: | ||||
|             case OpCode::Id::FMUL_R: | ||||
|             case OpCode::Id::FMUL_IMM: { | ||||
| @ -629,8 +678,8 @@ private: | ||||
|             case OpCode::Id::FMUL32_IMM: { | ||||
|                 // fmul32i doesn't have abs or neg bits.
 | ||||
|                 regs.SetRegisterToFloat( | ||||
|                     instr.gpr0, 0, regs.GetRegister(instr.gpr8) + " * " + GetImmediate32(instr), 1, | ||||
|                     1); | ||||
|                     instr.gpr0, 0, | ||||
|                     regs.GetRegisterAsFloat(instr.gpr8) + " * " + GetImmediate32(instr), 1, 1); | ||||
|                 break; | ||||
|             } | ||||
|             case OpCode::Id::FADD_C: | ||||
| @ -687,29 +736,29 @@ private: | ||||
|             break; | ||||
|         } | ||||
|         case OpCode::Type::Ffma: { | ||||
|             std::string op_a = regs.GetRegister(instr.gpr8); | ||||
|             std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); | ||||
|             std::string op_b = instr.ffma.negate_b ? "-" : ""; | ||||
|             std::string op_c = instr.ffma.negate_c ? "-" : ""; | ||||
| 
 | ||||
|             switch (opcode->GetId()) { | ||||
|             case OpCode::Id::FFMA_CR: { | ||||
|                 op_b += regs.GetUniform(instr.uniform, instr.gpr0); | ||||
|                 op_c += regs.GetRegister(instr.gpr39); | ||||
|                 op_c += regs.GetRegisterAsFloat(instr.gpr39); | ||||
|                 break; | ||||
|             } | ||||
|             case OpCode::Id::FFMA_RR: { | ||||
|                 op_b += regs.GetRegister(instr.gpr20); | ||||
|                 op_c += regs.GetRegister(instr.gpr39); | ||||
|                 op_b += regs.GetRegisterAsFloat(instr.gpr20); | ||||
|                 op_c += regs.GetRegisterAsFloat(instr.gpr39); | ||||
|                 break; | ||||
|             } | ||||
|             case OpCode::Id::FFMA_RC: { | ||||
|                 op_b += regs.GetRegister(instr.gpr39); | ||||
|                 op_b += regs.GetRegisterAsFloat(instr.gpr39); | ||||
|                 op_c += regs.GetUniform(instr.uniform, instr.gpr0); | ||||
|                 break; | ||||
|             } | ||||
|             case OpCode::Id::FFMA_IMM: { | ||||
|                 op_b += GetImmediate19(instr); | ||||
|                 op_c += regs.GetRegister(instr.gpr39); | ||||
|                 op_c += regs.GetRegisterAsFloat(instr.gpr39); | ||||
|                 break; | ||||
|             } | ||||
|             default: { | ||||
| @ -721,6 +770,32 @@ private: | ||||
|             regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " * " + op_b + " + " + op_c, 1, 1); | ||||
|             break; | ||||
|         } | ||||
|         case OpCode::Type::Conversion: { | ||||
|             ASSERT_MSG(instr.conversion.size == Register::Size::Word, "Unimplemented"); | ||||
|             ASSERT_MSG(!instr.conversion.selector, "Unimplemented"); | ||||
|             ASSERT_MSG(!instr.conversion.negate_a, "Unimplemented"); | ||||
|             ASSERT_MSG(!instr.conversion.saturate_a, "Unimplemented"); | ||||
| 
 | ||||
|             switch (opcode->GetId()) { | ||||
|             case OpCode::Id::I2I_R: | ||||
|             case OpCode::Id::I2F_R: { | ||||
|                 std::string op_a = | ||||
|                     regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_signed); | ||||
| 
 | ||||
|                 if (instr.conversion.abs_a) { | ||||
|                     op_a = "abs(" + op_a + ')'; | ||||
|                 } | ||||
| 
 | ||||
|                 regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_signed, 0, op_a, 1, 1); | ||||
|                 break; | ||||
|             } | ||||
|             default: { | ||||
|                 NGLOG_CRITICAL(HW_GPU, "Unhandled conversion instruction: {}", opcode->GetName()); | ||||
|                 UNREACHABLE(); | ||||
|             } | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|         case OpCode::Type::Memory: { | ||||
|             const Attribute::Index attribute = instr.attribute.fmt20.index; | ||||
| 
 | ||||
| @ -739,8 +814,8 @@ private: | ||||
|             } | ||||
|             case OpCode::Id::TEXS: { | ||||
|                 ASSERT_MSG(instr.attribute.fmt20.size == 4, "untested"); | ||||
|                 const std::string op_a = regs.GetRegister(instr.gpr8); | ||||
|                 const std::string op_b = regs.GetRegister(instr.gpr20); | ||||
|                 const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); | ||||
|                 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20); | ||||
|                 const std::string sampler = GetSampler(instr.sampler); | ||||
|                 const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; | ||||
|                 // Add an extra scope and declare the texture coords inside to prevent overwriting
 | ||||
| @ -765,7 +840,7 @@ private: | ||||
|         } | ||||
|         case OpCode::Type::FloatSetPredicate: { | ||||
|             std::string op_a = instr.fsetp.neg_a ? "-" : ""; | ||||
|             op_a += regs.GetRegister(instr.gpr8); | ||||
|             op_a += regs.GetRegisterAsFloat(instr.gpr8); | ||||
| 
 | ||||
|             if (instr.fsetp.abs_a) { | ||||
|                 op_a = "abs(" + op_a + ')'; | ||||
| @ -781,7 +856,7 @@ private: | ||||
|                 op_b += '(' + GetImmediate19(instr) + ')'; | ||||
|             } else { | ||||
|                 if (instr.is_b_gpr) { | ||||
|                     op_b += regs.GetRegister(instr.gpr20); | ||||
|                     op_b += regs.GetRegisterAsFloat(instr.gpr20); | ||||
|                 } else { | ||||
|                     op_b += regs.GetUniform(instr.uniform, instr.gpr0); | ||||
|                 } | ||||
| @ -816,7 +891,7 @@ private: | ||||
|         } | ||||
|         case OpCode::Type::FloatSet: { | ||||
|             std::string op_a = instr.fset.neg_a ? "-" : ""; | ||||
|             op_a += regs.GetRegister(instr.gpr8); | ||||
|             op_a += regs.GetRegisterAsFloat(instr.gpr8); | ||||
| 
 | ||||
|             if (instr.fset.abs_a) { | ||||
|                 op_a = "abs(" + op_a + ')'; | ||||
| @ -832,7 +907,7 @@ private: | ||||
|                     op_b += imm; | ||||
|             } else { | ||||
|                 if (instr.is_b_gpr) { | ||||
|                     op_b += regs.GetRegister(instr.gpr20); | ||||
|                     op_b += regs.GetRegisterAsFloat(instr.gpr20); | ||||
|                 } else { | ||||
|                     op_b += regs.GetUniform(instr.uniform, instr.gpr0); | ||||
|                 } | ||||
| @ -877,10 +952,10 @@ private: | ||||
| 
 | ||||
|                 // Final color output is currently hardcoded to GPR0-3 for fragment shaders
 | ||||
|                 if (stage == Maxwell3D::Regs::ShaderStage::Fragment) { | ||||
|                     shader.AddLine("color.r = " + regs.GetRegister(0) + ';'); | ||||
|                     shader.AddLine("color.g = " + regs.GetRegister(1) + ';'); | ||||
|                     shader.AddLine("color.b = " + regs.GetRegister(2) + ';'); | ||||
|                     shader.AddLine("color.a = " + regs.GetRegister(3) + ';'); | ||||
|                     shader.AddLine("color.r = " + regs.GetRegisterAsFloat(0) + ';'); | ||||
|                     shader.AddLine("color.g = " + regs.GetRegisterAsFloat(1) + ';'); | ||||
|                     shader.AddLine("color.b = " + regs.GetRegisterAsFloat(2) + ';'); | ||||
|                     shader.AddLine("color.a = " + regs.GetRegisterAsFloat(3) + ';'); | ||||
|                 } | ||||
| 
 | ||||
|                 shader.AddLine("return true;"); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 bunnei
						bunnei