Browse Source

Merge pull request #553 from Subv/iset

GPU: Implement the ISET family of shader instructions.
bunnei 8 years ago
parent
commit
281fd881a0

+ 16 - 0
src/video_core/engines/shader_bytecode.h

@@ -329,6 +329,15 @@ union Instruction {
         BitField<56, 1, u64> neg_imm;
     } fset;
 
+    union {
+        BitField<39, 3, u64> pred39;
+        BitField<42, 1, u64> neg_pred;
+        BitField<44, 1, u64> bf;
+        BitField<45, 2, PredOperation> op;
+        BitField<48, 1, u64> is_signed;
+        BitField<49, 3, PredCondition> cond;
+    } iset;
+
     union {
         BitField<10, 2, Register::Size> size;
         BitField<12, 1, u64> is_output_signed;
@@ -487,6 +496,9 @@ public:
         ISETP_C,
         ISETP_IMM,
         ISETP_R,
+        ISET_R,
+        ISET_C,
+        ISET_IMM,
         PSETP,
         XMAD_IMM,
         XMAD_CR,
@@ -506,6 +518,7 @@ public:
         Memory,
         FloatSet,
         FloatSetPredicate,
+        IntegerSet,
         IntegerSetPredicate,
         PredicateSetPredicate,
         Conversion,
@@ -677,6 +690,9 @@ private:
             INST("010010110110----", Id::ISETP_C, Type::IntegerSetPredicate, "ISETP_C"),
             INST("010110110110----", Id::ISETP_R, Type::IntegerSetPredicate, "ISETP_R"),
             INST("0011011-0110----", Id::ISETP_IMM, Type::IntegerSetPredicate, "ISETP_IMM"),
+            INST("010110110101----", Id::ISET_R, Type::IntegerSet, "ISET_R"),
+            INST("010010110101----", Id::ISET_C, Type::IntegerSet, "ISET_C"),
+            INST("0011011-0101----", Id::ISET_IMM, Type::IntegerSet, "ISET_IMM"),
             INST("0101000010010---", Id::PSETP, Type::PredicateSetPredicate, "PSETP"),
             INST("0011011-00------", Id::XMAD_IMM, Type::Arithmetic, "XMAD_IMM"),
             INST("0100111---------", Id::XMAD_CR, Type::Arithmetic, "XMAD_CR"),

+ 37 - 2
src/video_core/renderer_opengl/gl_shader_decompiler.cpp

@@ -1423,8 +1423,8 @@ private:
                 op_b = "abs(" + op_b + ')';
             }
 
-            // The fset instruction sets a register to 1.0 if the condition is true, and to 0
-            // otherwise.
+            // The fset instruction sets a register to 1.0 or -1 (depending on the bf bit) if the
+            // condition is true, and to 0 otherwise.
             std::string second_pred =
                 GetPredicateCondition(instr.fset.pred39, instr.fset.neg_pred != 0);
 
@@ -1442,6 +1442,41 @@ private:
             }
             break;
         }
+        case OpCode::Type::IntegerSet: {
+            std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, instr.iset.is_signed);
+
+            std::string op_b;
+
+            if (instr.is_b_imm) {
+                op_b = std::to_string(instr.alu.GetSignedImm20_20());
+            } else {
+                if (instr.is_b_gpr) {
+                    op_b = regs.GetRegisterAsInteger(instr.gpr20, 0, instr.iset.is_signed);
+                } else {
+                    op_b = regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset,
+                                           GLSLRegister::Type::Integer);
+                }
+            }
+
+            // The iset instruction sets a register to 1.0 or -1 (depending on the bf bit) if the
+            // condition is true, and to 0 otherwise.
+            std::string second_pred =
+                GetPredicateCondition(instr.iset.pred39, instr.iset.neg_pred != 0);
+
+            std::string comparator = GetPredicateComparison(instr.iset.cond);
+            std::string combiner = GetPredicateCombiner(instr.iset.op);
+
+            std::string predicate = "(((" + op_a + ") " + comparator + " (" + op_b + ")) " +
+                                    combiner + " (" + second_pred + "))";
+
+            if (instr.iset.bf) {
+                regs.SetRegisterToFloat(instr.gpr0, 0, predicate + " ? 1.0 : 0.0", 1, 1);
+            } else {
+                regs.SetRegisterToInteger(instr.gpr0, false, 0, predicate + " ? 0xFFFFFFFF : 0", 1,
+                                          1);
+            }
+            break;
+        }
         default: {
             switch (opcode->GetId()) {
             case OpCode::Id::EXIT: {