summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2018-08-19 17:01:48 -0400
committerGravatar GitHub2018-08-19 17:01:48 -0400
commit51ddb130c59e2d574a478f43c254292cd63df6b1 (patch)
tree0c9a6ea9a983186401f81c1d53b4a541143d17d4 /src
parentMerge pull request #1105 from Subv/convert_neg (diff)
parentShaders: Corrected the 'abs' and 'neg' bit usage in the float arithmetic inst... (diff)
downloadyuzu-51ddb130c59e2d574a478f43c254292cd63df6b1.tar.gz
yuzu-51ddb130c59e2d574a478f43c254292cd63df6b1.tar.xz
yuzu-51ddb130c59e2d574a478f43c254292cd63df6b1.zip
Merge pull request #1089 from Subv/neg_bits
Shaders: Corrected the 'abs' and 'neg' bit usage in the float arithmetic instructions.
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 096de9632..9413a81fb 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -293,6 +293,10 @@ union Instruction {
293 } alu; 293 } alu;
294 294
295 union { 295 union {
296 BitField<48, 1, u64> negate_b;
297 } fmul;
298
299 union {
296 BitField<48, 1, u64> is_signed; 300 BitField<48, 1, u64> is_signed;
297 } shift; 301 } shift;
298 302
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 44c6120b8..57cf9f213 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -747,6 +747,30 @@ private:
747 return op->second; 747 return op->second;
748 } 748 }
749 749
750 /**
751 * Transforms the input string GLSL operand into one that applies the abs() function and negates
752 * the output if necessary. When both abs and neg are true, the negation will be applied after
753 * taking the absolute value.
754 * @param operand The input operand to take the abs() of, negate, or both.
755 * @param abs Whether to apply the abs() function to the input operand.
756 * @param neg Whether to negate the input operand.
757 * @returns String corresponding to the operand after being transformed by the abs() and
758 * negation operations.
759 */
760 static std::string GetOperandAbsNeg(const std::string& operand, bool abs, bool neg) {
761 std::string result = operand;
762
763 if (abs) {
764 result = "abs(" + result + ')';
765 }
766
767 if (neg) {
768 result = "-(" + result + ')';
769 }
770
771 return result;
772 }
773
750 /* 774 /*
751 * Returns whether the instruction at the specified offset is a 'sched' instruction. 775 * Returns whether the instruction at the specified offset is a 'sched' instruction.
752 * Sched instructions always appear before a sequence of 3 instructions. 776 * Sched instructions always appear before a sequence of 3 instructions.
@@ -913,13 +937,6 @@ private:
913 switch (opcode->GetType()) { 937 switch (opcode->GetType()) {
914 case OpCode::Type::Arithmetic: { 938 case OpCode::Type::Arithmetic: {
915 std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); 939 std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
916 if (instr.alu.abs_a) {
917 op_a = "abs(" + op_a + ')';
918 }
919
920 if (instr.alu.negate_a) {
921 op_a = "-(" + op_a + ')';
922 }
923 940
924 std::string op_b; 941 std::string op_b;
925 942
@@ -934,17 +951,10 @@ private:
934 } 951 }
935 } 952 }
936 953
937 if (instr.alu.abs_b) {
938 op_b = "abs(" + op_b + ')';
939 }
940
941 if (instr.alu.negate_b) {
942 op_b = "-(" + op_b + ')';
943 }
944
945 switch (opcode->GetId()) { 954 switch (opcode->GetId()) {
946 case OpCode::Id::MOV_C: 955 case OpCode::Id::MOV_C:
947 case OpCode::Id::MOV_R: { 956 case OpCode::Id::MOV_R: {
957 // MOV does not have neither 'abs' nor 'neg' bits.
948 regs.SetRegisterToFloat(instr.gpr0, 0, op_b, 1, 1); 958 regs.SetRegisterToFloat(instr.gpr0, 0, op_b, 1, 1);
949 break; 959 break;
950 } 960 }
@@ -952,6 +962,8 @@ private:
952 case OpCode::Id::FMUL_C: 962 case OpCode::Id::FMUL_C:
953 case OpCode::Id::FMUL_R: 963 case OpCode::Id::FMUL_R:
954 case OpCode::Id::FMUL_IMM: { 964 case OpCode::Id::FMUL_IMM: {
965 // FMUL does not have 'abs' bits and only the second operand has a 'neg' bit.
966 op_b = GetOperandAbsNeg(op_b, false, instr.fmul.negate_b);
955 regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " * " + op_b, 1, 1, 967 regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " * " + op_b, 1, 1,
956 instr.alu.saturate_d); 968 instr.alu.saturate_d);
957 break; 969 break;
@@ -959,11 +971,14 @@ private:
959 case OpCode::Id::FADD_C: 971 case OpCode::Id::FADD_C:
960 case OpCode::Id::FADD_R: 972 case OpCode::Id::FADD_R:
961 case OpCode::Id::FADD_IMM: { 973 case OpCode::Id::FADD_IMM: {
974 op_a = GetOperandAbsNeg(op_a, instr.alu.abs_a, instr.alu.negate_a);
975 op_b = GetOperandAbsNeg(op_b, instr.alu.abs_b, instr.alu.negate_b);
962 regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " + " + op_b, 1, 1, 976 regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " + " + op_b, 1, 1,
963 instr.alu.saturate_d); 977 instr.alu.saturate_d);
964 break; 978 break;
965 } 979 }
966 case OpCode::Id::MUFU: { 980 case OpCode::Id::MUFU: {
981 op_a = GetOperandAbsNeg(op_a, instr.alu.abs_a, instr.alu.negate_a);
967 switch (instr.sub_op) { 982 switch (instr.sub_op) {
968 case SubOp::Cos: 983 case SubOp::Cos:
969 regs.SetRegisterToFloat(instr.gpr0, 0, "cos(" + op_a + ')', 1, 1, 984 regs.SetRegisterToFloat(instr.gpr0, 0, "cos(" + op_a + ')', 1, 1,
@@ -1003,6 +1018,9 @@ private:
1003 case OpCode::Id::FMNMX_C: 1018 case OpCode::Id::FMNMX_C:
1004 case OpCode::Id::FMNMX_R: 1019 case OpCode::Id::FMNMX_R:
1005 case OpCode::Id::FMNMX_IMM: { 1020 case OpCode::Id::FMNMX_IMM: {
1021 op_a = GetOperandAbsNeg(op_a, instr.alu.abs_a, instr.alu.negate_a);
1022 op_b = GetOperandAbsNeg(op_b, instr.alu.abs_b, instr.alu.negate_b);
1023
1006 std::string condition = 1024 std::string condition =
1007 GetPredicateCondition(instr.alu.fmnmx.pred, instr.alu.fmnmx.negate_pred != 0); 1025 GetPredicateCondition(instr.alu.fmnmx.pred, instr.alu.fmnmx.negate_pred != 0);
1008 std::string parameters = op_a + ',' + op_b; 1026 std::string parameters = op_a + ',' + op_b;
@@ -1016,7 +1034,7 @@ private:
1016 case OpCode::Id::RRO_R: 1034 case OpCode::Id::RRO_R:
1017 case OpCode::Id::RRO_IMM: { 1035 case OpCode::Id::RRO_IMM: {
1018 // Currently RRO is only implemented as a register move. 1036 // Currently RRO is only implemented as a register move.
1019 // Usage of `abs_b` and `negate_b` here should also be correct. 1037 op_b = GetOperandAbsNeg(op_b, instr.alu.abs_b, instr.alu.negate_b);
1020 regs.SetRegisterToFloat(instr.gpr0, 0, op_b, 1, 1); 1038 regs.SetRegisterToFloat(instr.gpr0, 0, op_b, 1, 1);
1021 LOG_WARNING(HW_GPU, "RRO instruction is incomplete"); 1039 LOG_WARNING(HW_GPU, "RRO instruction is incomplete");
1022 break; 1040 break;