Explorar el Código

Merge pull request #539 from bunnei/f2f-rounding

gl_shader_decompiler: F2F: Implement rounding modes.
bunnei hace 8 años
padre
commit
0cb7ce71e0

+ 12 - 3
src/video_core/engines/shader_bytecode.h

@@ -168,13 +168,22 @@ enum class SubOp : u64 {
     Min = 0x8,
     Min = 0x8,
 };
 };
 
 
-enum class FloatRoundingOp : u64 {
+enum class F2iRoundingOp : u64 {
     None = 0,
     None = 0,
     Floor = 1,
     Floor = 1,
     Ceil = 2,
     Ceil = 2,
     Trunc = 3,
     Trunc = 3,
 };
 };
 
 
+enum class F2fRoundingOp : u64 {
+    None = 0,
+    Pass = 3,
+    Round = 8,
+    Floor = 9,
+    Ceil = 10,
+    Trunc = 11,
+};
+
 enum class UniformType : u64 {
 enum class UniformType : u64 {
     UnsignedByte = 0,
     UnsignedByte = 0,
     SignedByte = 1,
     SignedByte = 1,
@@ -314,11 +323,11 @@ union Instruction {
         BitField<50, 1, u64> saturate_a;
         BitField<50, 1, u64> saturate_a;
 
 
         union {
         union {
-            BitField<39, 2, FloatRoundingOp> rounding;
+            BitField<39, 2, F2iRoundingOp> rounding;
         } f2i;
         } f2i;
 
 
         union {
         union {
-            BitField<39, 4, u64> rounding;
+            BitField<39, 4, F2fRoundingOp> rounding;
         } f2f;
         } f2f;
     } conversion;
     } conversion;
 
 

+ 23 - 7
src/video_core/renderer_opengl/gl_shader_decompiler.cpp

@@ -1056,10 +1056,27 @@ private:
                 break;
                 break;
             }
             }
             case OpCode::Id::F2F_R: {
             case OpCode::Id::F2F_R: {
-                // TODO(Subv): Implement rounding operations.
-                ASSERT_MSG(instr.conversion.f2f.rounding == 0, "Unimplemented rounding operation");
                 std::string op_a = regs.GetRegisterAsFloat(instr.gpr20);
                 std::string op_a = regs.GetRegisterAsFloat(instr.gpr20);
 
 
+                switch (instr.conversion.f2f.rounding) {
+                case Tegra::Shader::F2fRoundingOp::None:
+                    break;
+                case Tegra::Shader::F2fRoundingOp::Floor:
+                    op_a = "floor(" + op_a + ')';
+                    break;
+                case Tegra::Shader::F2fRoundingOp::Ceil:
+                    op_a = "ceil(" + op_a + ')';
+                    break;
+                case Tegra::Shader::F2fRoundingOp::Trunc:
+                    op_a = "trunc(" + op_a + ')';
+                    break;
+                default:
+                    NGLOG_CRITICAL(HW_GPU, "Unimplemented f2f rounding mode {}",
+                                   static_cast<u32>(instr.conversion.f2f.rounding.Value()));
+                    UNREACHABLE();
+                    break;
+                }
+
                 if (instr.conversion.abs_a) {
                 if (instr.conversion.abs_a) {
                     op_a = "abs(" + op_a + ')';
                     op_a = "abs(" + op_a + ')';
                 }
                 }
@@ -1074,17 +1091,16 @@ private:
                     op_a = "abs(" + op_a + ')';
                     op_a = "abs(" + op_a + ')';
                 }
                 }
 
 
-                using Tegra::Shader::FloatRoundingOp;
                 switch (instr.conversion.f2i.rounding) {
                 switch (instr.conversion.f2i.rounding) {
-                case FloatRoundingOp::None:
+                case Tegra::Shader::F2iRoundingOp::None:
                     break;
                     break;
-                case FloatRoundingOp::Floor:
+                case Tegra::Shader::F2iRoundingOp::Floor:
                     op_a = "floor(" + op_a + ')';
                     op_a = "floor(" + op_a + ')';
                     break;
                     break;
-                case FloatRoundingOp::Ceil:
+                case Tegra::Shader::F2iRoundingOp::Ceil:
                     op_a = "ceil(" + op_a + ')';
                     op_a = "ceil(" + op_a + ')';
                     break;
                     break;
-                case FloatRoundingOp::Trunc:
+                case Tegra::Shader::F2iRoundingOp::Trunc:
                     op_a = "trunc(" + op_a + ')';
                     op_a = "trunc(" + op_a + ')';
                     break;
                     break;
                 default:
                 default: