Просмотр исходного кода

Merge pull request #625 from Subv/imnmx

GPU: Implemented the IMNMX shader instruction.
bunnei 8 лет назад
Родитель
Сommit
639346bcfb

+ 17 - 3
src/video_core/engines/shader_bytecode.h

@@ -194,6 +194,13 @@ enum class UniformType : u64 {
     Double = 5,
     Double = 5,
 };
 };
 
 
+enum class IMinMaxExchange : u64 {
+    None = 0,
+    XLo = 1,
+    XMed = 2,
+    XHi = 3,
+};
+
 union Instruction {
 union Instruction {
     Instruction& operator=(const Instruction& instr) {
     Instruction& operator=(const Instruction& instr) {
         value = instr.value;
         value = instr.value;
@@ -278,6 +285,13 @@ union Instruction {
         BitField<49, 1, u64> negate_a;
         BitField<49, 1, u64> negate_a;
     } alu_integer;
     } alu_integer;
 
 
+    union {
+        BitField<39, 3, u64> pred;
+        BitField<42, 1, u64> negate_pred;
+        BitField<43, 2, IMinMaxExchange> exchange;
+        BitField<48, 1, u64> is_signed;
+    } imnmx;
+
     union {
     union {
         BitField<54, 1, u64> saturate;
         BitField<54, 1, u64> saturate;
         BitField<56, 1, u64> negate_a;
         BitField<56, 1, u64> negate_a;
@@ -700,9 +714,9 @@ private:
             INST("0100110001100---", Id::FMNMX_C, Type::Arithmetic, "FMNMX_C"),
             INST("0100110001100---", Id::FMNMX_C, Type::Arithmetic, "FMNMX_C"),
             INST("0101110001100---", Id::FMNMX_R, Type::Arithmetic, "FMNMX_R"),
             INST("0101110001100---", Id::FMNMX_R, Type::Arithmetic, "FMNMX_R"),
             INST("0011100-01100---", Id::FMNMX_IMM, Type::Arithmetic, "FMNMX_IMM"),
             INST("0011100-01100---", Id::FMNMX_IMM, Type::Arithmetic, "FMNMX_IMM"),
-            INST("0100110000100---", Id::IMNMX_C, Type::Arithmetic, "FMNMX_IMM"),
-            INST("0101110000100---", Id::IMNMX_R, Type::Arithmetic, "FMNMX_IMM"),
-            INST("0011100-00100---", Id::IMNMX_IMM, Type::Arithmetic, "FMNMX_IMM"),
+            INST("0100110000100---", Id::IMNMX_C, Type::ArithmeticInteger, "IMNMX_C"),
+            INST("0101110000100---", Id::IMNMX_R, Type::ArithmeticInteger, "IMNMX_R"),
+            INST("0011100-00100---", Id::IMNMX_IMM, Type::ArithmeticInteger, "IMNMX_IMM"),
             INST("0100110000000---", Id::BFE_C, Type::Bfe, "BFE_C"),
             INST("0100110000000---", Id::BFE_C, Type::Bfe, "BFE_C"),
             INST("0101110000000---", Id::BFE_R, Type::Bfe, "BFE_R"),
             INST("0101110000000---", Id::BFE_R, Type::Bfe, "BFE_R"),
             INST("0011100-00000---", Id::BFE_IMM, Type::Bfe, "BFE_IMM"),
             INST("0011100-00000---", Id::BFE_IMM, Type::Bfe, "BFE_IMM"),

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

@@ -1127,6 +1127,20 @@ private:
                 WriteLogicOperation(instr.gpr0, instr.alu.lop.operation, op_a, op_b);
                 WriteLogicOperation(instr.gpr0, instr.alu.lop.operation, op_a, op_b);
                 break;
                 break;
             }
             }
+            case OpCode::Id::IMNMX_C:
+            case OpCode::Id::IMNMX_R:
+            case OpCode::Id::IMNMX_IMM: {
+                ASSERT_MSG(instr.imnmx.exchange == Tegra::Shader::IMinMaxExchange::None,
+                           "Unimplemented");
+                std::string condition =
+                    GetPredicateCondition(instr.imnmx.pred, instr.imnmx.negate_pred != 0);
+                std::string parameters = op_a + ',' + op_b;
+                regs.SetRegisterToInteger(instr.gpr0, instr.imnmx.is_signed, 0,
+                                          '(' + condition + ") ? min(" + parameters + ") : max(" +
+                                              parameters + ')',
+                                          1, 1);
+                break;
+            }
             default: {
             default: {
                 LOG_CRITICAL(HW_GPU, "Unhandled ArithmeticInteger instruction: {}",
                 LOG_CRITICAL(HW_GPU, "Unhandled ArithmeticInteger instruction: {}",
                              opcode->GetName());
                              opcode->GetName());