summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Subv2018-08-16 09:05:16 -0500
committerGravatar Subv2018-08-18 10:22:42 -0500
commit2e95ba2e9c67d16456fb9f700cfe3da837e16a73 (patch)
tree83c1c00e9a39179dd72db272c9d49bbe7cdfa5a9 /src
parentMerge pull request #1075 from lioncash/include (diff)
downloadyuzu-2e95ba2e9c67d16456fb9f700cfe3da837e16a73.tar.gz
yuzu-2e95ba2e9c67d16456fb9f700cfe3da837e16a73.tar.xz
yuzu-2e95ba2e9c67d16456fb9f700cfe3da837e16a73.zip
Shaders: Corrected the 'abs' and 'neg' bit usage in the float arithmetic instructions.
We should definitely audit our shader generator for more errors like this.
Diffstat (limited to 'src')
-rw-r--r--src/video_core/engines/shader_bytecode.h4
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp50
2 files changed, 38 insertions, 16 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 2526ebf28..f438fa809 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -283,6 +283,10 @@ union Instruction {
283 } alu; 283 } alu;
284 284
285 union { 285 union {
286 BitField<48, 1, u64> negate_b;
287 } fmul;
288
289 union {
286 BitField<48, 1, u64> is_signed; 290 BitField<48, 1, u64> is_signed;
287 } shift; 291 } shift;
288 292
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index e0dfdbb9f..e899237e5 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -741,6 +741,30 @@ private:
741 return op->second; 741 return op->second;
742 } 742 }
743 743
744 /**
745 * Transforms the input string GLSL operand into one that applies the abs() function and negates
746 * the output if necessary. When both abs and neg are true, the negation will be applied after
747 * taking the absolute value.
748 * @param operand The input operand to take the abs() of, negate, or both.
749 * @param abs Whether to apply the abs() function to the input operand.
750 * @param neg Whether to negate the input operand.
751 * @returns String corresponding to the operand after being transformed by the abs() and
752 * negation operations.
753 */
754 static std::string GetOperandAbsNeg(const std::string& operand, bool abs, bool neg) {
755 std::string result = operand;
756
757 if (abs) {
758 result = "abs(" + result + ')';
759 }
760
761 if (neg) {
762 result = "-(" + result + ')';
763 }
764
765 return result;
766 }
767
744 /* 768 /*
745 * Returns whether the instruction at the specified offset is a 'sched' instruction. 769 * Returns whether the instruction at the specified offset is a 'sched' instruction.
746 * Sched instructions always appear before a sequence of 3 instructions. 770 * Sched instructions always appear before a sequence of 3 instructions.
@@ -857,13 +881,6 @@ private:
857 switch (opcode->GetType()) { 881 switch (opcode->GetType()) {
858 case OpCode::Type::Arithmetic: { 882 case OpCode::Type::Arithmetic: {
859 std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); 883 std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
860 if (instr.alu.abs_a) {
861 op_a = "abs(" + op_a + ')';
862 }
863
864 if (instr.alu.negate_a) {
865 op_a = "-(" + op_a + ')';
866 }
867 884
868 std::string op_b; 885 std::string op_b;
869 886
@@ -878,17 +895,10 @@ private:
878 } 895 }
879 } 896 }
880 897
881 if (instr.alu.abs_b) {
882 op_b = "abs(" + op_b + ')';
883 }
884
885 if (instr.alu.negate_b) {
886 op_b = "-(" + op_b + ')';
887 }
888
889 switch (opcode->GetId()) { 898 switch (opcode->GetId()) {
890 case OpCode::Id::MOV_C: 899 case OpCode::Id::MOV_C:
891 case OpCode::Id::MOV_R: { 900 case OpCode::Id::MOV_R: {
901 // MOV does not have neither 'abs' nor 'neg' bits.
892 regs.SetRegisterToFloat(instr.gpr0, 0, op_b, 1, 1); 902 regs.SetRegisterToFloat(instr.gpr0, 0, op_b, 1, 1);
893 break; 903 break;
894 } 904 }
@@ -896,6 +906,8 @@ private:
896 case OpCode::Id::FMUL_C: 906 case OpCode::Id::FMUL_C:
897 case OpCode::Id::FMUL_R: 907 case OpCode::Id::FMUL_R:
898 case OpCode::Id::FMUL_IMM: { 908 case OpCode::Id::FMUL_IMM: {
909 // FMUL does not have 'abs' bits and only the second operand has a 'neg' bit.
910 op_b = GetOperandAbsNeg(op_b, false, instr.fmul.negate_b);
899 regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " * " + op_b, 1, 1, 911 regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " * " + op_b, 1, 1,
900 instr.alu.saturate_d); 912 instr.alu.saturate_d);
901 break; 913 break;
@@ -903,11 +915,14 @@ private:
903 case OpCode::Id::FADD_C: 915 case OpCode::Id::FADD_C:
904 case OpCode::Id::FADD_R: 916 case OpCode::Id::FADD_R:
905 case OpCode::Id::FADD_IMM: { 917 case OpCode::Id::FADD_IMM: {
918 op_a = GetOperandAbsNeg(op_a, instr.alu.abs_a, instr.alu.negate_a);
919 op_b = GetOperandAbsNeg(op_b, instr.alu.abs_b, instr.alu.negate_b);
906 regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " + " + op_b, 1, 1, 920 regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " + " + op_b, 1, 1,
907 instr.alu.saturate_d); 921 instr.alu.saturate_d);
908 break; 922 break;
909 } 923 }
910 case OpCode::Id::MUFU: { 924 case OpCode::Id::MUFU: {
925 op_a = GetOperandAbsNeg(op_a, instr.alu.abs_a, instr.alu.negate_a);
911 switch (instr.sub_op) { 926 switch (instr.sub_op) {
912 case SubOp::Cos: 927 case SubOp::Cos:
913 regs.SetRegisterToFloat(instr.gpr0, 0, "cos(" + op_a + ')', 1, 1, 928 regs.SetRegisterToFloat(instr.gpr0, 0, "cos(" + op_a + ')', 1, 1,
@@ -947,6 +962,9 @@ private:
947 case OpCode::Id::FMNMX_C: 962 case OpCode::Id::FMNMX_C:
948 case OpCode::Id::FMNMX_R: 963 case OpCode::Id::FMNMX_R:
949 case OpCode::Id::FMNMX_IMM: { 964 case OpCode::Id::FMNMX_IMM: {
965 op_a = GetOperandAbsNeg(op_a, instr.alu.abs_a, instr.alu.negate_a);
966 op_b = GetOperandAbsNeg(op_b, instr.alu.abs_b, instr.alu.negate_b);
967
950 std::string condition = 968 std::string condition =
951 GetPredicateCondition(instr.alu.fmnmx.pred, instr.alu.fmnmx.negate_pred != 0); 969 GetPredicateCondition(instr.alu.fmnmx.pred, instr.alu.fmnmx.negate_pred != 0);
952 std::string parameters = op_a + ',' + op_b; 970 std::string parameters = op_a + ',' + op_b;
@@ -960,7 +978,7 @@ private:
960 case OpCode::Id::RRO_R: 978 case OpCode::Id::RRO_R:
961 case OpCode::Id::RRO_IMM: { 979 case OpCode::Id::RRO_IMM: {
962 // Currently RRO is only implemented as a register move. 980 // Currently RRO is only implemented as a register move.
963 // Usage of `abs_b` and `negate_b` here should also be correct. 981 op_b = GetOperandAbsNeg(op_b, instr.alu.abs_b, instr.alu.negate_b);
964 regs.SetRegisterToFloat(instr.gpr0, 0, op_b, 1, 1); 982 regs.SetRegisterToFloat(instr.gpr0, 0, op_b, 1, 1);
965 LOG_WARNING(HW_GPU, "RRO instruction is incomplete"); 983 LOG_WARNING(HW_GPU, "RRO instruction is incomplete");
966 break; 984 break;