diff options
Diffstat (limited to 'src/video_core')
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 9 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 39 | 
2 files changed, 46 insertions, 2 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 9f17225f8..ec8dbd370 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -330,6 +330,15 @@ union Instruction {      } 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;          BitField<13, 1, u64> is_input_signed; diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 37fbb94da..8521be4a1 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/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: {  | 
