diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index ab45cfbef..2cda1e63e 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -168,13 +168,22 @@ enum class SubOp : u64 { Min = 0x8, }; -enum class FloatRoundingOp : u64 { +enum class F2iRoundingOp : u64 { None = 0, Floor = 1, Ceil = 2, Trunc = 3, }; +enum class F2fRoundingOp : u64 { + None = 0, + Pass = 3, + Round = 8, + Floor = 9, + Ceil = 10, + Trunc = 11, +}; + enum class UniformType : u64 { UnsignedByte = 0, SignedByte = 1, @@ -314,11 +323,11 @@ union Instruction { BitField<50, 1, u64> saturate_a; union { - BitField<39, 2, FloatRoundingOp> rounding; + BitField<39, 2, F2iRoundingOp> rounding; } f2i; union { - BitField<39, 4, u64> rounding; + BitField<39, 4, F2fRoundingOp> rounding; } f2f; } conversion; diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index f84cedc1d..8e249584f 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -1056,10 +1056,27 @@ 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); + 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(instr.conversion.f2f.rounding.Value())); + UNREACHABLE(); + break; + } + if (instr.conversion.abs_a) { op_a = "abs(" + op_a + ')'; } @@ -1074,17 +1091,16 @@ private: op_a = "abs(" + op_a + ')'; } - using Tegra::Shader::FloatRoundingOp; switch (instr.conversion.f2i.rounding) { - case FloatRoundingOp::None: + case Tegra::Shader::F2iRoundingOp::None: break; - case FloatRoundingOp::Floor: + case Tegra::Shader::F2iRoundingOp::Floor: op_a = "floor(" + op_a + ')'; break; - case FloatRoundingOp::Ceil: + case Tegra::Shader::F2iRoundingOp::Ceil: op_a = "ceil(" + op_a + ')'; break; - case FloatRoundingOp::Trunc: + case Tegra::Shader::F2iRoundingOp::Trunc: op_a = "trunc(" + op_a + ')'; break; default: