diff options
| author | bunnei <bunneidev@gmail.com> | 2018-06-05 22:01:29 -0400 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-06-05 22:01:29 -0400 | 
| commit | 5fb99e6a166786eab5e1f8c656fe8431b3e11255 (patch) | |
| tree | f9a689d4c732095234417560247a32622df39be8 /src/video_core | |
| parent | 6e8e1a4110a3cb9b009173e5deac1f1bdc40cbb0 (diff) | |
| parent | 4b89348c0046e69c3419a587d2bc19e1c411e39c (diff) | |
Merge pull request #516 from Subv/f2i_r
GPU: Implemented the F2I_R shader instruction.
Diffstat (limited to 'src/video_core')
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 24 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 47 | 
2 files changed, 64 insertions, 7 deletions
| diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 38757c038..4eb507325 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -173,6 +173,13 @@ enum class SubOp : u64 {      Min = 0x8,  }; +enum class FloatRoundingOp : u64 { +    None = 0, +    Floor = 1, +    Ceil = 2, +    Trunc = 3, +}; +  union Instruction {      Instruction& operator=(const Instruction& instr) {          value = instr.value; @@ -290,11 +297,20 @@ union Instruction {      union {          BitField<10, 2, Register::Size> size; -        BitField<13, 1, u64> is_signed; +        BitField<12, 1, u64> is_output_signed; +        BitField<13, 1, u64> is_input_signed;          BitField<41, 2, u64> selector;          BitField<45, 1, u64> negate_a;          BitField<49, 1, u64> abs_a;          BitField<50, 1, u64> saturate_a; + +        union { +            BitField<39, 2, FloatRoundingOp> rounding; +        } f2i; + +        union { +            BitField<39, 4, u64> rounding; +        } f2f;      } conversion;      union { @@ -560,9 +576,9 @@ private:              INST("0100110010101---", Id::F2F_C, Type::Conversion, "F2F_C"),              INST("0101110010101---", Id::F2F_R, Type::Conversion, "F2F_R"),              INST("0011100-10101---", Id::F2F_IMM, Type::Conversion, "F2F_IMM"), -            INST("0100110010110---", Id::F2I_C, Type::Arithmetic, "F2I_C"), -            INST("0101110010110---", Id::F2I_R, Type::Arithmetic, "F2I_R"), -            INST("0011100-10110---", Id::F2I_IMM, Type::Arithmetic, "F2I_IMM"), +            INST("0100110010110---", Id::F2I_C, Type::Conversion, "F2I_C"), +            INST("0101110010110---", Id::F2I_R, Type::Conversion, "F2I_R"), +            INST("0011100-10110---", Id::F2I_IMM, Type::Conversion, "F2I_IMM"),              INST("0100110010011---", Id::MOV_C, Type::Arithmetic, "MOV_C"),              INST("0101110010011---", Id::MOV_R, Type::Arithmetic, "MOV_R"),              INST("0011100-10011---", Id::MOV_IMM, Type::Arithmetic, "MOV_IMM"), diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index f886e49ca..4a41e7798 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -991,18 +991,20 @@ private:                  ASSERT_MSG(!instr.conversion.selector, "Unimplemented");                  std::string op_a = -                    regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_signed); +                    regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_input_signed);                  if (instr.conversion.abs_a) {                      op_a = "abs(" + op_a + ')';                  } -                regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_signed, 0, op_a, 1, 1); +                regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1, +                                          1);                  break;              }              case OpCode::Id::I2F_R: { +                ASSERT_MSG(!instr.conversion.selector, "Unimplemented");                  std::string op_a = -                    regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_signed); +                    regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_input_signed);                  if (instr.conversion.abs_a) {                      op_a = "abs(" + op_a + ')'; @@ -1012,6 +1014,8 @@ private:                  break;              }              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);                  if (instr.conversion.abs_a) { @@ -1021,6 +1025,43 @@ private:                  regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1);                  break;              } +            case OpCode::Id::F2I_R: { +                std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); + +                if (instr.conversion.abs_a) { +                    op_a = "abs(" + op_a + ')'; +                } + +                using Tegra::Shader::FloatRoundingOp; +                switch (instr.conversion.f2i.rounding) { +                case FloatRoundingOp::None: +                    break; +                case FloatRoundingOp::Floor: +                    op_a = "floor(" + op_a + ')'; +                    break; +                case FloatRoundingOp::Ceil: +                    op_a = "ceil(" + op_a + ')'; +                    break; +                case FloatRoundingOp::Trunc: +                    op_a = "trunc(" + op_a + ')'; +                    break; +                default: +                    NGLOG_CRITICAL(HW_GPU, "Unimplemented f2i rounding mode {}", +                                   static_cast<u32>(instr.conversion.f2i.rounding.Value())); +                    UNREACHABLE(); +                    break; +                } + +                if (instr.conversion.is_output_signed) { +                    op_a = "int(" + op_a + ')'; +                } else { +                    op_a = "uint(" + op_a + ')'; +                } + +                regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1, +                                          1); +                break; +            }              default: {                  NGLOG_CRITICAL(HW_GPU, "Unhandled conversion instruction: {}", opcode->GetName());                  UNREACHABLE(); | 
