summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2018-06-10 16:50:38 +0200
committerGitHub <noreply@github.com>2018-06-10 16:50:38 +0200
commit281fd881a00ec7e17ee2e2e0711f30bf69efa965 (patch)
treead1a89a8b7686e2947e7eca53716e4e45e27085d
parentMerge pull request #550 from Subv/ssy (diff)
parentGPU: Implement the iset family of shader instructions. (diff)
downloadyuzu-281fd881a00ec7e17ee2e2e0711f30bf69efa965.tar
yuzu-281fd881a00ec7e17ee2e2e0711f30bf69efa965.tar.gz
yuzu-281fd881a00ec7e17ee2e2e0711f30bf69efa965.tar.bz2
yuzu-281fd881a00ec7e17ee2e2e0711f30bf69efa965.tar.lz
yuzu-281fd881a00ec7e17ee2e2e0711f30bf69efa965.tar.xz
yuzu-281fd881a00ec7e17ee2e2e0711f30bf69efa965.tar.zst
yuzu-281fd881a00ec7e17ee2e2e0711f30bf69efa965.zip
-rw-r--r--src/video_core/engines/shader_bytecode.h16
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp39
2 files changed, 53 insertions, 2 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index d748026b8..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;
@@ -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"),
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: {