diff options
-rw-r--r-- | src/video_core/engines/shader_bytecode.h | 14 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 51 |
2 files changed, 53 insertions, 12 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 51cf4af9f..c368fa7fd 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -4,6 +4,7 @@ #pragma once +#include <cstring> #include <map> #include <string> #include "common/bit_field.h" @@ -289,6 +290,7 @@ enum class SubOp : u64 { Lg2 = 0x3, Rcp = 0x4, Rsq = 0x5, + Min = 0x8, }; union Instruction { @@ -307,11 +309,22 @@ union Instruction { BitField<39, 8, Register> gpr39; union { + BitField<20, 19, u64> imm20; BitField<45, 1, u64> negate_b; BitField<46, 1, u64> abs_a; BitField<48, 1, u64> negate_a; BitField<49, 1, u64> abs_b; BitField<50, 1, u64> abs_d; + BitField<56, 1, u64> negate_imm; + + float GetImm20() const { + float result{}; + u32 imm{static_cast<u32>(imm20)}; + imm <<= 12; + imm |= negate_imm ? 0x80000000 : 0; + std::memcpy(&result, &imm, sizeof(imm)); + return result; + } } alu; union { @@ -319,6 +332,7 @@ union Instruction { BitField<49, 1, u64> negate_c; } ffma; + BitField<61, 1, u64> is_b_imm; BitField<60, 1, u64> is_b_gpr; BitField<59, 1, u64> is_c_gpr; diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 1d8057927..aa435e5cc 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -190,6 +190,11 @@ private: } } + /// Generates code representing an immediate value + static std::string GetImmediate(const Instruction& instr) { + return std::to_string(instr.alu.GetImm20()); + } + /// Generates code representing a temporary (GPR) register. std::string GetRegister(const Register& reg, unsigned elem = 0) { if (stage == Maxwell3D::Regs::ShaderStage::Fragment && reg < 4) { @@ -269,24 +274,32 @@ private: } std::string op_b = instr.alu.negate_b ? "-" : ""; - if (instr.is_b_gpr) { - op_b += GetRegister(instr.gpr20); + + if (instr.is_b_imm) { + op_b += GetImmediate(instr); } else { - op_b += GetUniform(instr.uniform); + if (instr.is_b_gpr) { + op_b += GetRegister(instr.gpr20); + } else { + op_b += GetUniform(instr.uniform); + } } + if (instr.alu.abs_b) { op_b = "abs(" + op_b + ")"; } switch (instr.opcode.EffectiveOpCode()) { case OpCode::Id::FMUL_C: - case OpCode::Id::FMUL_R: { - SetDest(0, dest, op_a + " * " + op_b, 1, 1); + case OpCode::Id::FMUL_R: + case OpCode::Id::FMUL_IMM: { + SetDest(0, dest, op_a + " * " + op_b, 1, 1, instr.alu.abs_d); break; } case OpCode::Id::FADD_C: - case OpCode::Id::FADD_R: { - SetDest(0, dest, op_a + " + " + op_b, 1, 1); + case OpCode::Id::FADD_R: + case OpCode::Id::FADD_IMM: { + SetDest(0, dest, op_a + " + " + op_b, 1, 1, instr.alu.abs_d); break; } case OpCode::Id::MUFU: { @@ -316,16 +329,28 @@ private: std::string dest = GetRegister(instr.gpr0); std::string op_a = GetRegister(instr.gpr8); - std::string op_b = instr.ffma.negate_b ? "-" : ""; - op_b += GetUniform(instr.uniform); - std::string op_c = instr.ffma.negate_c ? "-" : ""; - op_c += GetRegister(instr.gpr39); switch (instr.opcode.EffectiveOpCode()) { case OpCode::Id::FFMA_CR: { - SetDest(0, dest, op_a + " * " + op_b + " + " + op_c, 1, 1); + op_b += GetUniform(instr.uniform); + op_c += GetRegister(instr.gpr39); + break; + } + case OpCode::Id::FFMA_RR: { + op_b += GetRegister(instr.gpr20); + op_c += GetRegister(instr.gpr39); + break; + } + case OpCode::Id::FFMA_RC: { + op_b += GetRegister(instr.gpr39); + op_c += GetUniform(instr.uniform); + break; + } + case OpCode::Id::FFMA_IMM: { + op_b += GetImmediate(instr); + op_c += GetRegister(instr.gpr39); break; } default: { @@ -336,6 +361,8 @@ private: break; } } + + SetDest(0, dest, op_a + " * " + op_b + " + " + op_c, 1, 1); break; } case OpCode::Type::Memory: { |