mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-12-24 09:20:58 +01:00
gl_shader_decompiler: Add support for TEXS instruction.
This commit is contained in:
parent
5ba71369ac
commit
8b4443c966
2 changed files with 43 additions and 12 deletions
|
@ -16,10 +16,6 @@ struct Register {
|
||||||
|
|
||||||
constexpr Register(u64 value) : value(value) {}
|
constexpr Register(u64 value) : value(value) {}
|
||||||
|
|
||||||
constexpr u64 GetIndex() const {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr operator u64() const {
|
constexpr operator u64() const {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -71,6 +67,19 @@ union Attribute {
|
||||||
u64 value;
|
u64 value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
union Sampler {
|
||||||
|
Sampler() = default;
|
||||||
|
|
||||||
|
constexpr Sampler(u64 value) : value(value) {}
|
||||||
|
|
||||||
|
enum class Index : u64 {
|
||||||
|
Sampler_0 = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
BitField<36, 13, Index> index;
|
||||||
|
u64 value;
|
||||||
|
};
|
||||||
|
|
||||||
union Uniform {
|
union Uniform {
|
||||||
BitField<20, 14, u64> offset;
|
BitField<20, 14, u64> offset;
|
||||||
BitField<34, 5, u64> index;
|
BitField<34, 5, u64> index;
|
||||||
|
@ -295,7 +304,6 @@ union Instruction {
|
||||||
BitField<20, 8, Register> gpr20;
|
BitField<20, 8, Register> gpr20;
|
||||||
BitField<20, 7, SubOp> sub_op;
|
BitField<20, 7, SubOp> sub_op;
|
||||||
BitField<28, 8, Register> gpr28;
|
BitField<28, 8, Register> gpr28;
|
||||||
BitField<36, 13, u64> imm36;
|
|
||||||
BitField<39, 8, Register> gpr39;
|
BitField<39, 8, Register> gpr39;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
|
@ -316,6 +324,7 @@ union Instruction {
|
||||||
|
|
||||||
Attribute attribute;
|
Attribute attribute;
|
||||||
Uniform uniform;
|
Uniform uniform;
|
||||||
|
Sampler sampler;
|
||||||
|
|
||||||
u64 hex;
|
u64 hex;
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,6 +17,7 @@ using Tegra::Shader::Attribute;
|
||||||
using Tegra::Shader::Instruction;
|
using Tegra::Shader::Instruction;
|
||||||
using Tegra::Shader::OpCode;
|
using Tegra::Shader::OpCode;
|
||||||
using Tegra::Shader::Register;
|
using Tegra::Shader::Register;
|
||||||
|
using Tegra::Shader::Sampler;
|
||||||
using Tegra::Shader::SubOp;
|
using Tegra::Shader::SubOp;
|
||||||
using Tegra::Shader::Uniform;
|
using Tegra::Shader::Uniform;
|
||||||
|
|
||||||
|
@ -186,13 +187,13 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates code representing a temporary (GPR) register.
|
/// Generates code representing a temporary (GPR) register.
|
||||||
std::string GetRegister(const Register& reg) {
|
std::string GetRegister(const Register& reg, unsigned elem = 0) {
|
||||||
if (stage == Maxwell3D::Regs::ShaderStage::Fragment && reg.GetIndex() < 4) {
|
if (stage == Maxwell3D::Regs::ShaderStage::Fragment && reg < 4) {
|
||||||
// GPRs 0-3 are output color for the fragment shader
|
// GPRs 0-3 are output color for the fragment shader
|
||||||
return std::string{"color."} + "rgba"[reg.GetIndex()];
|
return std::string{"color."} + "rgba"[reg + elem];
|
||||||
}
|
}
|
||||||
|
|
||||||
return *declr_register.insert("register_" + std::to_string(reg)).first;
|
return *declr_register.insert("register_" + std::to_string(reg + elem)).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates code representing a uniform (C buffer) register.
|
/// Generates code representing a uniform (C buffer) register.
|
||||||
|
@ -201,6 +202,15 @@ private:
|
||||||
return 'c' + std::to_string(reg.index) + '[' + std::to_string(reg.offset) + ']';
|
return 'c' + std::to_string(reg.index) + '[' + std::to_string(reg.offset) + ']';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generates code representing a texture sampler.
|
||||||
|
std::string GetSampler(const Sampler& sampler) const {
|
||||||
|
// TODO(Subv): Support more than just texture sampler 0
|
||||||
|
ASSERT_MSG(sampler.index == Sampler::Index::Sampler_0, "unsupported");
|
||||||
|
const unsigned index{static_cast<unsigned>(sampler.index.Value()) -
|
||||||
|
static_cast<unsigned>(Sampler::Index::Sampler_0)};
|
||||||
|
return "tex[" + std::to_string(index) + "]";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds code that calls a subroutine.
|
* Adds code that calls a subroutine.
|
||||||
* @param subroutine the subroutine to call.
|
* @param subroutine the subroutine to call.
|
||||||
|
@ -245,7 +255,7 @@ private:
|
||||||
|
|
||||||
switch (OpCode::GetInfo(instr.opcode).type) {
|
switch (OpCode::GetInfo(instr.opcode).type) {
|
||||||
case OpCode::Type::Arithmetic: {
|
case OpCode::Type::Arithmetic: {
|
||||||
ASSERT(!instr.alu.abs_d);
|
ASSERT_MSG(!instr.alu.abs_d, "unimplemented");
|
||||||
|
|
||||||
std::string dest = GetRegister(instr.gpr0);
|
std::string dest = GetRegister(instr.gpr0);
|
||||||
std::string op_a = instr.alu.negate_a ? "-" : "";
|
std::string op_a = instr.alu.negate_a ? "-" : "";
|
||||||
|
@ -330,15 +340,27 @@ private:
|
||||||
|
|
||||||
switch (instr.opcode.EffectiveOpCode()) {
|
switch (instr.opcode.EffectiveOpCode()) {
|
||||||
case OpCode::Id::LD_A: {
|
case OpCode::Id::LD_A: {
|
||||||
ASSERT(instr.attribute.fmt20.size == 0);
|
ASSERT_MSG(instr.attribute.fmt20.size == 0, "untested");
|
||||||
SetDest(instr.attribute.fmt20.element, gpr0, GetInputAttribute(attribute), 1, 4);
|
SetDest(instr.attribute.fmt20.element, gpr0, GetInputAttribute(attribute), 1, 4);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OpCode::Id::ST_A: {
|
case OpCode::Id::ST_A: {
|
||||||
ASSERT(instr.attribute.fmt20.size == 0);
|
ASSERT_MSG(instr.attribute.fmt20.size == 0, "untested");
|
||||||
SetDest(instr.attribute.fmt20.element, GetOutputAttribute(attribute), gpr0, 4, 1);
|
SetDest(instr.attribute.fmt20.element, GetOutputAttribute(attribute), gpr0, 4, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case OpCode::Id::TEXS: {
|
||||||
|
ASSERT_MSG(instr.attribute.fmt20.size == 4, "untested");
|
||||||
|
const std::string op_a = GetRegister(instr.gpr8);
|
||||||
|
const std::string op_b = GetRegister(instr.gpr20);
|
||||||
|
const std::string sampler = GetSampler(instr.sampler);
|
||||||
|
const std::string coord = "vec2(" + op_a + ", " + op_b + ")";
|
||||||
|
const std::string texture = "texture(" + sampler + ", " + coord + ")";
|
||||||
|
for (unsigned elem = 0; elem < instr.attribute.fmt20.size; ++elem) {
|
||||||
|
SetDest(elem, GetRegister(instr.gpr0, elem), texture, 1, 4);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
LOG_CRITICAL(HW_GPU, "Unhandled memory instruction: 0x%02x (%s): 0x%08x",
|
LOG_CRITICAL(HW_GPU, "Unhandled memory instruction: 0x%02x (%s): 0x%08x",
|
||||||
static_cast<unsigned>(instr.opcode.EffectiveOpCode()),
|
static_cast<unsigned>(instr.opcode.EffectiveOpCode()),
|
||||||
|
|
Loading…
Reference in a new issue