Merge pull request #1299 from FernandoS27/texture-sanatize
shader_decompiler: Asserts for Texture Instructions
This commit is contained in:
		| @@ -271,6 +271,15 @@ enum class TextureProcessMode : u64 { | ||||
|     LLA = 7  // Load LOD. The A is unknown, does not appear to differ with LL | ||||
| }; | ||||
|  | ||||
| enum class TextureMiscMode : u64 { | ||||
|     DC, | ||||
|     AOFFI, // Uses Offset | ||||
|     NDV, | ||||
|     NODEP, | ||||
|     MZ, | ||||
|     PTP, | ||||
| }; | ||||
|  | ||||
| enum class IpaInterpMode : u64 { Linear = 0, Perspective = 1, Flat = 2, Sc = 3 }; | ||||
| enum class IpaSampleMode : u64 { Default = 0, Centroid = 1, Offset = 2 }; | ||||
|  | ||||
| @@ -590,42 +599,127 @@ union Instruction { | ||||
|         BitField<28, 1, u64> array; | ||||
|         BitField<29, 2, TextureType> texture_type; | ||||
|         BitField<31, 4, u64> component_mask; | ||||
|         BitField<49, 1, u64> nodep_flag; | ||||
|         BitField<50, 1, u64> dc_flag; | ||||
|         BitField<54, 1, u64> aoffi_flag; | ||||
|         BitField<55, 3, TextureProcessMode> process_mode; | ||||
|  | ||||
|         bool IsComponentEnabled(std::size_t component) const { | ||||
|             return ((1ull << component) & component_mask) != 0; | ||||
|         } | ||||
|  | ||||
|         TextureProcessMode GetTextureProcessMode() const { | ||||
|             return process_mode; | ||||
|         } | ||||
|  | ||||
|         bool UsesMiscMode(TextureMiscMode mode) const { | ||||
|             switch (mode) { | ||||
|             case TextureMiscMode::DC: | ||||
|                 return dc_flag != 0; | ||||
|             case TextureMiscMode::NODEP: | ||||
|                 return nodep_flag != 0; | ||||
|             case TextureMiscMode::AOFFI: | ||||
|                 return aoffi_flag != 0; | ||||
|             default: | ||||
|                 break; | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
|     } tex; | ||||
|  | ||||
|     union { | ||||
|         BitField<22, 6, TextureQueryType> query_type; | ||||
|         BitField<31, 4, u64> component_mask; | ||||
|         BitField<49, 1, u64> nodep_flag; | ||||
|  | ||||
|         bool UsesMiscMode(TextureMiscMode mode) const { | ||||
|             switch (mode) { | ||||
|             case TextureMiscMode::NODEP: | ||||
|                 return nodep_flag != 0; | ||||
|             default: | ||||
|                 break; | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
|     } txq; | ||||
|  | ||||
|     union { | ||||
|         BitField<28, 1, u64> array; | ||||
|         BitField<29, 2, TextureType> texture_type; | ||||
|         BitField<31, 4, u64> component_mask; | ||||
|         BitField<35, 1, u64> ndv_flag; | ||||
|         BitField<49, 1, u64> nodep_flag; | ||||
|  | ||||
|         bool IsComponentEnabled(std::size_t component) const { | ||||
|             return ((1ull << component) & component_mask) != 0; | ||||
|         } | ||||
|  | ||||
|         bool UsesMiscMode(TextureMiscMode mode) const { | ||||
|             switch (mode) { | ||||
|             case TextureMiscMode::NDV: | ||||
|                 return (ndv_flag != 0); | ||||
|             case TextureMiscMode::NODEP: | ||||
|                 return (nodep_flag != 0); | ||||
|             default: | ||||
|                 break; | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
|     } tmml; | ||||
|  | ||||
|     union { | ||||
|         BitField<28, 1, u64> array; | ||||
|         BitField<29, 2, TextureType> texture_type; | ||||
|         BitField<35, 1, u64> ndv_flag; | ||||
|         BitField<49, 1, u64> nodep_flag; | ||||
|         BitField<50, 1, u64> dc_flag; | ||||
|         BitField<54, 2, u64> info; | ||||
|         BitField<56, 2, u64> component; | ||||
|  | ||||
|         bool UsesMiscMode(TextureMiscMode mode) const { | ||||
|             switch (mode) { | ||||
|             case TextureMiscMode::NDV: | ||||
|                 return ndv_flag != 0; | ||||
|             case TextureMiscMode::NODEP: | ||||
|                 return nodep_flag != 0; | ||||
|             case TextureMiscMode::DC: | ||||
|                 return dc_flag != 0; | ||||
|             case TextureMiscMode::AOFFI: | ||||
|                 return info == 1; | ||||
|             case TextureMiscMode::PTP: | ||||
|                 return info == 2; | ||||
|             default: | ||||
|                 break; | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
|     } tld4; | ||||
|  | ||||
|     union { | ||||
|         BitField<49, 1, u64> nodep_flag; | ||||
|         BitField<50, 1, u64> dc_flag; | ||||
|         BitField<51, 1, u64> aoffi_flag; | ||||
|         BitField<52, 2, u64> component; | ||||
|  | ||||
|         bool UsesMiscMode(TextureMiscMode mode) const { | ||||
|             switch (mode) { | ||||
|             case TextureMiscMode::DC: | ||||
|                 return dc_flag != 0; | ||||
|             case TextureMiscMode::NODEP: | ||||
|                 return nodep_flag != 0; | ||||
|             case TextureMiscMode::AOFFI: | ||||
|                 return aoffi_flag != 0; | ||||
|             default: | ||||
|                 break; | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
|     } tld4s; | ||||
|  | ||||
|     union { | ||||
|         BitField<0, 8, Register> gpr0; | ||||
|         BitField<28, 8, Register> gpr28; | ||||
|         BitField<49, 1, u64> nodep; | ||||
|         BitField<49, 1, u64> nodep_flag; | ||||
|         BitField<50, 3, u64> component_mask_selector; | ||||
|         BitField<53, 4, u64> texture_info; | ||||
|  | ||||
| @@ -645,6 +739,37 @@ union Instruction { | ||||
|             UNREACHABLE(); | ||||
|         } | ||||
|  | ||||
|         TextureProcessMode GetTextureProcessMode() const { | ||||
|             switch (texture_info) { | ||||
|             case 0: | ||||
|             case 2: | ||||
|             case 6: | ||||
|             case 8: | ||||
|             case 9: | ||||
|             case 11: | ||||
|                 return TextureProcessMode::LZ; | ||||
|             case 3: | ||||
|             case 5: | ||||
|             case 13: | ||||
|                 return TextureProcessMode::LL; | ||||
|             default: | ||||
|                 break; | ||||
|             } | ||||
|             return TextureProcessMode::None; | ||||
|         } | ||||
|  | ||||
|         bool UsesMiscMode(TextureMiscMode mode) const { | ||||
|             switch (mode) { | ||||
|             case TextureMiscMode::DC: | ||||
|                 return (texture_info >= 4 && texture_info <= 6) || texture_info == 9; | ||||
|             case TextureMiscMode::NODEP: | ||||
|                 return nodep_flag != 0; | ||||
|             default: | ||||
|                 break; | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         bool IsArrayTexture() const { | ||||
|             // TEXS only supports Texture2D arrays. | ||||
|             return texture_info >= 7 && texture_info <= 9; | ||||
| @@ -673,6 +798,7 @@ union Instruction { | ||||
|     } texs; | ||||
|  | ||||
|     union { | ||||
|         BitField<49, 1, u64> nodep_flag; | ||||
|         BitField<53, 4, u64> texture_info; | ||||
|  | ||||
|         TextureType GetTextureType() const { | ||||
| @@ -693,6 +819,26 @@ union Instruction { | ||||
|             UNREACHABLE(); | ||||
|         } | ||||
|  | ||||
|         TextureProcessMode GetTextureProcessMode() const { | ||||
|             if (texture_info == 1 || texture_info == 5 || texture_info == 12) | ||||
|                 return TextureProcessMode::LL; | ||||
|             return TextureProcessMode::LZ; | ||||
|         } | ||||
|  | ||||
|         bool UsesMiscMode(TextureMiscMode mode) const { | ||||
|             switch (mode) { | ||||
|             case TextureMiscMode::AOFFI: | ||||
|                 return texture_info == 12 || texture_info == 4; | ||||
|             case TextureMiscMode::MZ: | ||||
|                 return texture_info == 5; | ||||
|             case TextureMiscMode::NODEP: | ||||
|                 return nodep_flag != 0; | ||||
|             default: | ||||
|                 break; | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         bool IsArrayTexture() const { | ||||
|             // TEXS only supports Texture2D arrays. | ||||
|             return texture_info == 8; | ||||
|   | ||||
| @@ -938,8 +938,6 @@ private: | ||||
|         // TEXS has two destination registers and a swizzle. The first two elements in the swizzle | ||||
|         // go into gpr0+0 and gpr0+1, and the rest goes into gpr28+0 and gpr28+1 | ||||
|  | ||||
|         ASSERT_MSG(instr.texs.nodep == 0, "TEXS nodep not implemented"); | ||||
|  | ||||
|         std::size_t written_components = 0; | ||||
|         for (u32 component = 0; component < 4; ++component) { | ||||
|             if (!instr.texs.IsComponentEnabled(component)) { | ||||
| @@ -1853,6 +1851,13 @@ private: | ||||
|                 Tegra::Shader::TextureType texture_type{instr.tex.texture_type}; | ||||
|                 std::string coord; | ||||
|  | ||||
|                 ASSERT_MSG(!instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), | ||||
|                            "NODEP is not implemented"); | ||||
|                 ASSERT_MSG(!instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI), | ||||
|                            "AOFFI is not implemented"); | ||||
|                 ASSERT_MSG(!instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC), | ||||
|                            "DC is not implemented"); | ||||
|  | ||||
|                 switch (texture_type) { | ||||
|                 case Tegra::Shader::TextureType::Texture1D: { | ||||
|                     const std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||||
| @@ -1935,6 +1940,11 @@ private: | ||||
|                 Tegra::Shader::TextureType texture_type{instr.texs.GetTextureType()}; | ||||
|                 bool is_array{instr.texs.IsArrayTexture()}; | ||||
|  | ||||
|                 ASSERT_MSG(!instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), | ||||
|                            "NODEP is not implemented"); | ||||
|                 ASSERT_MSG(!instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC), | ||||
|                            "DC is not implemented"); | ||||
|  | ||||
|                 switch (texture_type) { | ||||
|                 case Tegra::Shader::TextureType::Texture2D: { | ||||
|                     if (is_array) { | ||||
| @@ -1971,6 +1981,13 @@ private: | ||||
|                 ASSERT(instr.tlds.IsArrayTexture() == false); | ||||
|                 std::string coord; | ||||
|  | ||||
|                 ASSERT_MSG(!instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), | ||||
|                            "NODEP is not implemented"); | ||||
|                 ASSERT_MSG(!instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI), | ||||
|                            "AOFFI is not implemented"); | ||||
|                 ASSERT_MSG(!instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::MZ), | ||||
|                            "MZ is not implemented"); | ||||
|  | ||||
|                 switch (instr.tlds.GetTextureType()) { | ||||
|                 case Tegra::Shader::TextureType::Texture2D: { | ||||
|                     if (instr.tlds.IsArrayTexture()) { | ||||
| @@ -1999,6 +2016,17 @@ private: | ||||
|                 ASSERT(instr.tld4.array == 0); | ||||
|                 std::string coord; | ||||
|  | ||||
|                 ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), | ||||
|                            "NODEP is not implemented"); | ||||
|                 ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI), | ||||
|                            "AOFFI is not implemented"); | ||||
|                 ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC), | ||||
|                            "DC is not implemented"); | ||||
|                 ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::NDV), | ||||
|                            "NDV is not implemented"); | ||||
|                 ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::PTP), | ||||
|                            "PTP is not implemented"); | ||||
|  | ||||
|                 switch (instr.tld4.texture_type) { | ||||
|                 case Tegra::Shader::TextureType::Texture2D: { | ||||
|                     const std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||||
| @@ -2036,6 +2064,13 @@ private: | ||||
|                 break; | ||||
|             } | ||||
|             case OpCode::Id::TLD4S: { | ||||
|                 ASSERT_MSG(!instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), | ||||
|                            "NODEP is not implemented"); | ||||
|                 ASSERT_MSG(!instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI), | ||||
|                            "AOFFI is not implemented"); | ||||
|                 ASSERT_MSG(!instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC), | ||||
|                            "DC is not implemented"); | ||||
|  | ||||
|                 const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); | ||||
|                 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20); | ||||
|                 // TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction. | ||||
| @@ -2048,6 +2083,9 @@ private: | ||||
|                 break; | ||||
|             } | ||||
|             case OpCode::Id::TXQ: { | ||||
|                 ASSERT_MSG(!instr.txq.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), | ||||
|                            "NODEP is not implemented"); | ||||
|  | ||||
|                 // TODO: the new commits on the texture refactor, change the way samplers work. | ||||
|                 // Sadly, not all texture instructions specify the type of texture their sampler | ||||
|                 // uses. This must be fixed at a later instance. | ||||
| @@ -2068,6 +2106,11 @@ private: | ||||
|                 break; | ||||
|             } | ||||
|             case OpCode::Id::TMML: { | ||||
|                 ASSERT_MSG(!instr.tmml.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), | ||||
|                            "NODEP is not implemented"); | ||||
|                 ASSERT_MSG(!instr.tmml.UsesMiscMode(Tegra::Shader::TextureMiscMode::NDV), | ||||
|                            "NDV is not implemented"); | ||||
|  | ||||
|                 const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); | ||||
|                 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||||
|                 const bool is_array = instr.tmml.array != 0; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user