summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/video_core/engines/shader_bytecode.h14
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp51
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: {