Bläddra i källkod

Shaders: Implemented IADD3

tech4me 8 år sedan
förälder
incheckning
a6dd577d02

+ 23 - 1
src/video_core/engines/shader_bytecode.h

@@ -213,6 +213,18 @@ enum class XmadMode : u64 {
     CBcc = 4,
     CBcc = 4,
 };
 };
 
 
+enum class IAdd3Mode : u64 {
+    None = 0,
+    RightShift = 1,
+    LeftShift = 2,
+};
+
+enum class IAdd3Height : u64 {
+    None = 0,
+    LowerHalfWord = 1,
+    UpperHalfWord = 2,
+};
+
 enum class FlowCondition : u64 {
 enum class FlowCondition : u64 {
     Always = 0xF,
     Always = 0xF,
     Fcsm_Tr = 0x1C, // TODO(bunnei): What is this used for?
     Fcsm_Tr = 0x1C, // TODO(bunnei): What is this used for?
@@ -338,6 +350,16 @@ union Instruction {
         BitField<48, 1, u64> is_signed;
         BitField<48, 1, u64> is_signed;
     } imnmx;
     } imnmx;
 
 
+    union {
+        BitField<31, 2, IAdd3Height> height_c;
+        BitField<33, 2, IAdd3Height> height_b;
+        BitField<35, 2, IAdd3Height> height_a;
+        BitField<37, 2, IAdd3Mode> mode;
+        BitField<49, 1, u64> neg_c;
+        BitField<50, 1, u64> neg_b;
+        BitField<51, 1, u64> neg_a;
+    } iadd3;
+
     union {
     union {
         BitField<54, 1, u64> saturate;
         BitField<54, 1, u64> saturate;
         BitField<56, 1, u64> negate_a;
         BitField<56, 1, u64> negate_a;
@@ -636,7 +658,7 @@ public:
         IADD_C,
         IADD_C,
         IADD_R,
         IADD_R,
         IADD_IMM,
         IADD_IMM,
-        IADD3_C,
+        IADD3_C, // Add 3 Integers
         IADD3_R,
         IADD3_R,
         IADD3_IMM,
         IADD3_IMM,
         IADD32I,
         IADD32I,

+ 61 - 0
src/video_core/renderer_opengl/gl_shader_decompiler.cpp

@@ -1287,6 +1287,67 @@ private:
                                           instr.alu.saturate_d);
                                           instr.alu.saturate_d);
                 break;
                 break;
             }
             }
+            case OpCode::Id::IADD3_C:
+            case OpCode::Id::IADD3_R:
+            case OpCode::Id::IADD3_IMM: {
+                std::string op_c = regs.GetRegisterAsInteger(instr.gpr39);
+
+                auto apply_height = [](auto height, auto& oprand) {
+                    switch (height) {
+                    case Tegra::Shader::IAdd3Height::None:
+                        break;
+                    case Tegra::Shader::IAdd3Height::LowerHalfWord:
+                        oprand = "((" + oprand + ") & 0xFFFF)";
+                        break;
+                    case Tegra::Shader::IAdd3Height::UpperHalfWord:
+                        oprand = "((" + oprand + ") >> 16)";
+                        break;
+                    default:
+                        LOG_CRITICAL(HW_GPU, "Unhandled IADD3 height: {}",
+                                     static_cast<u32>(height.Value()));
+                        UNREACHABLE();
+                    }
+                };
+
+                if (opcode->GetId() == OpCode::Id::IADD3_R) {
+                    apply_height(instr.iadd3.height_a, op_a);
+                    apply_height(instr.iadd3.height_b, op_b);
+                    apply_height(instr.iadd3.height_c, op_c);
+                }
+
+                if (instr.iadd3.neg_a)
+                    op_a = "-(" + op_a + ')';
+
+                if (instr.iadd3.neg_b)
+                    op_b = "-(" + op_b + ')';
+
+                if (instr.iadd3.neg_c)
+                    op_c = "-(" + op_c + ')';
+
+                std::string result;
+                if (opcode->GetId() == OpCode::Id::IADD3_R) {
+                    switch (instr.iadd3.mode) {
+                    case Tegra::Shader::IAdd3Mode::RightShift:
+                        // TODO(tech4me): According to
+                        // https://envytools.readthedocs.io/en/latest/hw/graph/maxwell/cuda/int.html?highlight=iadd3
+                        // The addition between op_a and op_b should be done in uint33, more
+                        // investigation required
+                        result = "(((" + op_a + " + " + op_b + ") >> 16) + " + op_c + ')';
+                        break;
+                    case Tegra::Shader::IAdd3Mode::LeftShift:
+                        result = "(((" + op_a + " + " + op_b + ") << 16) + " + op_c + ')';
+                        break;
+                    default:
+                        result = '(' + op_a + " + " + op_b + " + " + op_c + ')';
+                        break;
+                    }
+                } else {
+                    result = '(' + op_a + " + " + op_b + " + " + op_c + ')';
+                }
+
+                regs.SetRegisterToInteger(instr.gpr0, true, 0, result, 1, 1);
+                break;
+            }
             case OpCode::Id::ISCADD_C:
             case OpCode::Id::ISCADD_C:
             case OpCode::Id::ISCADD_R:
             case OpCode::Id::ISCADD_R:
             case OpCode::Id::ISCADD_IMM: {
             case OpCode::Id::ISCADD_IMM: {