diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index dabf98b74..e0dfdbb9f 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -367,20 +367,23 @@ public: } /// Generates code representing a uniform (C buffer) register, interpreted as the input type. - std::string GetUniform(u64 index, u64 offset, GLSLRegister::Type type) { + std::string GetUniform(u64 index, u64 offset, GLSLRegister::Type type, + Register::Size size = Register::Size::Word) { declr_const_buffers[index].MarkAsUsed(index, offset, stage); std::string value = 'c' + std::to_string(index) + '[' + std::to_string(offset / 4) + "][" + std::to_string(offset % 4) + ']'; if (type == GLSLRegister::Type::Float) { - return value; + // Do nothing, default } else if (type == GLSLRegister::Type::Integer) { - return "floatBitsToInt(" + value + ')'; + value = "floatBitsToInt(" + value + ')'; } else if (type == GLSLRegister::Type::UnsignedInteger) { - return "floatBitsToUint(" + value + ')'; + value = "floatBitsToUint(" + value + ')'; } else { UNREACHABLE(); } + + return ConvertIntegerSize(value, size); } std::string GetUniformIndirect(u64 cbuf_index, s64 offset, const std::string& index_str, @@ -1247,20 +1250,41 @@ private: op_a = "abs(" + op_a + ')'; } + if (instr.conversion.negate_a) { + op_a = "-(" + op_a + ')'; + } + regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1, 1, instr.alu.saturate_d, 0, instr.conversion.dest_size); break; } - case OpCode::Id::I2F_R: { + case OpCode::Id::I2F_R: + case OpCode::Id::I2F_C: { ASSERT_MSG(instr.conversion.dest_size == Register::Size::Word, "Unimplemented"); ASSERT_MSG(!instr.conversion.selector, "Unimplemented"); - std::string op_a = regs.GetRegisterAsInteger( - instr.gpr20, 0, instr.conversion.is_input_signed, instr.conversion.src_size); + + std::string op_a{}; + + if (instr.is_b_gpr) { + op_a = + regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_input_signed, + instr.conversion.src_size); + } else { + op_a = regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset, + instr.conversion.is_input_signed + ? GLSLRegister::Type::Integer + : GLSLRegister::Type::UnsignedInteger, + instr.conversion.src_size); + } if (instr.conversion.abs_a) { op_a = "abs(" + op_a + ')'; } + if (instr.conversion.negate_a) { + op_a = "-(" + op_a + ')'; + } + regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1); break; } @@ -1269,6 +1293,14 @@ private: ASSERT_MSG(instr.conversion.src_size == Register::Size::Word, "Unimplemented"); std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); + if (instr.conversion.abs_a) { + op_a = "abs(" + op_a + ')'; + } + + if (instr.conversion.negate_a) { + op_a = "-(" + op_a + ')'; + } + switch (instr.conversion.f2f.rounding) { case Tegra::Shader::F2fRoundingOp::None: break; @@ -1291,19 +1323,27 @@ private: break; } + regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1, instr.alu.saturate_d); + break; + } + case OpCode::Id::F2I_R: + case OpCode::Id::F2I_C: { + ASSERT_MSG(instr.conversion.src_size == Register::Size::Word, "Unimplemented"); + std::string op_a{}; + + if (instr.is_b_gpr) { + op_a = regs.GetRegisterAsFloat(instr.gpr20); + } else { + op_a = regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset, + GLSLRegister::Type::Float); + } + if (instr.conversion.abs_a) { op_a = "abs(" + op_a + ')'; } - regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1, instr.alu.saturate_d); - break; - } - case OpCode::Id::F2I_R: { - ASSERT_MSG(instr.conversion.src_size == Register::Size::Word, "Unimplemented"); - std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); - - if (instr.conversion.abs_a) { - op_a = "abs(" + op_a + ')'; + if (instr.conversion.negate_a) { + op_a = "-(" + op_a + ')'; } switch (instr.conversion.f2i.rounding) {