mirror of
https://git.h3cjp.net/H3cJP/citra.git
synced 2024-11-28 06:52:47 +00:00
Merge pull request #1299 from FernandoS27/texture-sanatize
shader_decompiler: Asserts for Texture Instructions
This commit is contained in:
commit
6415f81bb8
|
@ -271,6 +271,15 @@ enum class TextureProcessMode : u64 {
|
||||||
LLA = 7 // Load LOD. The A is unknown, does not appear to differ with LL
|
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 IpaInterpMode : u64 { Linear = 0, Perspective = 1, Flat = 2, Sc = 3 };
|
||||||
enum class IpaSampleMode : u64 { Default = 0, Centroid = 1, Offset = 2 };
|
enum class IpaSampleMode : u64 { Default = 0, Centroid = 1, Offset = 2 };
|
||||||
|
|
||||||
|
@ -590,42 +599,127 @@ union Instruction {
|
||||||
BitField<28, 1, u64> array;
|
BitField<28, 1, u64> array;
|
||||||
BitField<29, 2, TextureType> texture_type;
|
BitField<29, 2, TextureType> texture_type;
|
||||||
BitField<31, 4, u64> component_mask;
|
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;
|
BitField<55, 3, TextureProcessMode> process_mode;
|
||||||
|
|
||||||
bool IsComponentEnabled(std::size_t component) const {
|
bool IsComponentEnabled(std::size_t component) const {
|
||||||
return ((1ull << component) & component_mask) != 0;
|
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;
|
} tex;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
BitField<22, 6, TextureQueryType> query_type;
|
BitField<22, 6, TextureQueryType> query_type;
|
||||||
BitField<31, 4, u64> component_mask;
|
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;
|
} txq;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
BitField<28, 1, u64> array;
|
BitField<28, 1, u64> array;
|
||||||
BitField<29, 2, TextureType> texture_type;
|
BitField<29, 2, TextureType> texture_type;
|
||||||
BitField<31, 4, u64> component_mask;
|
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 {
|
bool IsComponentEnabled(std::size_t component) const {
|
||||||
return ((1ull << component) & component_mask) != 0;
|
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;
|
} tmml;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
BitField<28, 1, u64> array;
|
BitField<28, 1, u64> array;
|
||||||
BitField<29, 2, TextureType> texture_type;
|
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;
|
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;
|
} tld4;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
|
BitField<49, 1, u64> nodep_flag;
|
||||||
|
BitField<50, 1, u64> dc_flag;
|
||||||
|
BitField<51, 1, u64> aoffi_flag;
|
||||||
BitField<52, 2, u64> component;
|
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;
|
} tld4s;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
BitField<0, 8, Register> gpr0;
|
BitField<0, 8, Register> gpr0;
|
||||||
BitField<28, 8, Register> gpr28;
|
BitField<28, 8, Register> gpr28;
|
||||||
BitField<49, 1, u64> nodep;
|
BitField<49, 1, u64> nodep_flag;
|
||||||
BitField<50, 3, u64> component_mask_selector;
|
BitField<50, 3, u64> component_mask_selector;
|
||||||
BitField<53, 4, u64> texture_info;
|
BitField<53, 4, u64> texture_info;
|
||||||
|
|
||||||
|
@ -645,6 +739,37 @@ union Instruction {
|
||||||
UNREACHABLE();
|
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 {
|
bool IsArrayTexture() const {
|
||||||
// TEXS only supports Texture2D arrays.
|
// TEXS only supports Texture2D arrays.
|
||||||
return texture_info >= 7 && texture_info <= 9;
|
return texture_info >= 7 && texture_info <= 9;
|
||||||
|
@ -673,6 +798,7 @@ union Instruction {
|
||||||
} texs;
|
} texs;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
|
BitField<49, 1, u64> nodep_flag;
|
||||||
BitField<53, 4, u64> texture_info;
|
BitField<53, 4, u64> texture_info;
|
||||||
|
|
||||||
TextureType GetTextureType() const {
|
TextureType GetTextureType() const {
|
||||||
|
@ -693,6 +819,26 @@ union Instruction {
|
||||||
UNREACHABLE();
|
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 {
|
bool IsArrayTexture() const {
|
||||||
// TEXS only supports Texture2D arrays.
|
// TEXS only supports Texture2D arrays.
|
||||||
return texture_info == 8;
|
return texture_info == 8;
|
||||||
|
|
|
@ -938,8 +938,6 @@ private:
|
||||||
// TEXS has two destination registers and a swizzle. The first two elements in the swizzle
|
// 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
|
// 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;
|
std::size_t written_components = 0;
|
||||||
for (u32 component = 0; component < 4; ++component) {
|
for (u32 component = 0; component < 4; ++component) {
|
||||||
if (!instr.texs.IsComponentEnabled(component)) {
|
if (!instr.texs.IsComponentEnabled(component)) {
|
||||||
|
@ -1853,6 +1851,13 @@ private:
|
||||||
Tegra::Shader::TextureType texture_type{instr.tex.texture_type};
|
Tegra::Shader::TextureType texture_type{instr.tex.texture_type};
|
||||||
std::string coord;
|
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) {
|
switch (texture_type) {
|
||||||
case Tegra::Shader::TextureType::Texture1D: {
|
case Tegra::Shader::TextureType::Texture1D: {
|
||||||
const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
|
const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
|
||||||
|
@ -1935,6 +1940,11 @@ private:
|
||||||
Tegra::Shader::TextureType texture_type{instr.texs.GetTextureType()};
|
Tegra::Shader::TextureType texture_type{instr.texs.GetTextureType()};
|
||||||
bool is_array{instr.texs.IsArrayTexture()};
|
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) {
|
switch (texture_type) {
|
||||||
case Tegra::Shader::TextureType::Texture2D: {
|
case Tegra::Shader::TextureType::Texture2D: {
|
||||||
if (is_array) {
|
if (is_array) {
|
||||||
|
@ -1971,6 +1981,13 @@ private:
|
||||||
ASSERT(instr.tlds.IsArrayTexture() == false);
|
ASSERT(instr.tlds.IsArrayTexture() == false);
|
||||||
std::string coord;
|
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()) {
|
switch (instr.tlds.GetTextureType()) {
|
||||||
case Tegra::Shader::TextureType::Texture2D: {
|
case Tegra::Shader::TextureType::Texture2D: {
|
||||||
if (instr.tlds.IsArrayTexture()) {
|
if (instr.tlds.IsArrayTexture()) {
|
||||||
|
@ -1999,6 +2016,17 @@ private:
|
||||||
ASSERT(instr.tld4.array == 0);
|
ASSERT(instr.tld4.array == 0);
|
||||||
std::string coord;
|
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) {
|
switch (instr.tld4.texture_type) {
|
||||||
case Tegra::Shader::TextureType::Texture2D: {
|
case Tegra::Shader::TextureType::Texture2D: {
|
||||||
const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
|
const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
|
||||||
|
@ -2036,6 +2064,13 @@ private:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OpCode::Id::TLD4S: {
|
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_a = regs.GetRegisterAsFloat(instr.gpr8);
|
||||||
const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20);
|
const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20);
|
||||||
// TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction.
|
// TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction.
|
||||||
|
@ -2048,6 +2083,9 @@ private:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OpCode::Id::TXQ: {
|
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.
|
// 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
|
// Sadly, not all texture instructions specify the type of texture their sampler
|
||||||
// uses. This must be fixed at a later instance.
|
// uses. This must be fixed at a later instance.
|
||||||
|
@ -2068,6 +2106,11 @@ private:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OpCode::Id::TMML: {
|
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_a = regs.GetRegisterAsFloat(instr.gpr8);
|
||||||
const std::string op_b = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
|
const std::string op_b = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
|
||||||
const bool is_array = instr.tmml.array != 0;
|
const bool is_array = instr.tmml.array != 0;
|
||||||
|
|
Loading…
Reference in a new issue