diff --git a/src/core/gte.cpp b/src/core/gte.cpp index 54694587a..006d0aa2c 100644 --- a/src/core/gte.cpp +++ b/src/core/gte.cpp @@ -624,16 +624,41 @@ static void RTPS(const s16 V[3], u8 shift, bool lm, bool last) if (g_settings.gpu_pgxp_enable) { - // this can potentially use increased precision on Z - const float precise_z = std::max((float)REGS.H / 2.f, (float)z / 4096.0f); - const float precise_h_div_sz = (float)REGS.H / precise_z; - const float fofx = ((float)REGS.OFX / (float)(1 << 16)); - const float fofy = ((float)REGS.OFY / (float)(1 << 16)); - float precise_x = fofx + ((float)REGS.IR1 * precise_h_div_sz) * ((g_settings.gpu_widescreen_hack) ? 0.75f : 1.00f); - float precise_y = fofy + ((float)REGS.IR2 * precise_h_div_sz); + float precise_sz3, precise_ir1, precise_ir2; - precise_x = std::clamp(precise_x, -0x400, 0x3ff); - precise_y = std::clamp(precise_y, -0x400, 0x3ff); + if (g_settings.gpu_pgxp_preserve_proj_fp) + { + precise_sz3 = float(z) / 4096.0f; + precise_ir1 = float(x) / (static_cast(1 << shift)); + precise_ir2 = float(y) / (static_cast(1 << shift)); + if (lm) + { + precise_ir1 = std::clamp(precise_ir1, float(IR123_MIN_VALUE), float(IR123_MAX_VALUE)); + precise_ir2 = std::clamp(precise_ir2, float(IR123_MIN_VALUE), float(IR123_MAX_VALUE)); + } + else + { + precise_ir1 = std::min(precise_ir1, float(IR123_MAX_VALUE)); + precise_ir2 = std::min(precise_ir2, float(IR123_MAX_VALUE)); + } + } + else + { + precise_sz3 = float(REGS.SZ3); + precise_ir1 = float(REGS.IR1); + precise_ir2 = float(REGS.IR2); + } + + // this can potentially use increased precision on Z + const float precise_z = std::max(float(REGS.H) / 2.0f, precise_sz3); + const float precise_h_div_sz = float(REGS.H) / precise_z; + const float fofx = float(REGS.OFX) / float(1 << 16); + const float fofy = float(REGS.OFY) / float(1 << 16); + float precise_x = fofx + (precise_ir1 * precise_h_div_sz) * ((g_settings.gpu_widescreen_hack) ? 0.75f : 1.00f); + float precise_y = fofy + (precise_ir2 * precise_h_div_sz); + + precise_x = std::clamp(precise_x, -1024.0f, 1023.0f); + precise_y = std::clamp(precise_y, -1024.0f, 1023.0f); PGXP::GTE_PushSXYZ2f(precise_x, precise_y, precise_z, REGS.dr32[14]); } diff --git a/src/core/host_interface.cpp b/src/core/host_interface.cpp index 8ced54443..1795d51f1 100644 --- a/src/core/host_interface.cpp +++ b/src/core/host_interface.cpp @@ -434,6 +434,7 @@ void HostInterface::SetDefaultSettings(SettingsInterface& si) si.SetBoolValue("GPU", "PGXPTextureCorrection", true); si.SetBoolValue("GPU", "PGXPVertexCache", false); si.SetBoolValue("GPU", "PGXPCPU", false); + si.SetBoolValue("GPU", "PGXPPreserveProjFP", false); si.SetStringValue("Display", "CropMode", Settings::GetDisplayCropModeName(Settings::DEFAULT_DISPLAY_CROP_MODE)); si.SetIntValue("Display", "ActiveStartOffset", 0); diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 3f9ee7994..2e2ca2bfa 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -149,6 +149,7 @@ void Settings::Load(SettingsInterface& si) gpu_pgxp_texture_correction = si.GetBoolValue("GPU", "PGXPTextureCorrection", true); gpu_pgxp_vertex_cache = si.GetBoolValue("GPU", "PGXPVertexCache", false); gpu_pgxp_cpu = si.GetBoolValue("GPU", "PGXPCPU", false); + gpu_pgxp_preserve_proj_fp = si.GetBoolValue("GPU", "PGXPPreserveProjFP", false); display_crop_mode = ParseDisplayCropMode( @@ -273,6 +274,7 @@ void Settings::Save(SettingsInterface& si) const si.SetBoolValue("GPU", "PGXPTextureCorrection", gpu_pgxp_texture_correction); si.SetBoolValue("GPU", "PGXPVertexCache", gpu_pgxp_vertex_cache); si.SetBoolValue("GPU", "PGXPCPU", gpu_pgxp_cpu); + si.SetBoolValue("GPU", "PGXPPreserveProjFP", gpu_pgxp_preserve_proj_fp); si.SetStringValue("Display", "CropMode", GetDisplayCropModeName(display_crop_mode)); si.SetIntValue("Display", "ActiveStartOffset", display_active_start_offset); diff --git a/src/core/settings.h b/src/core/settings.h index 01a5a37cc..d5d589c44 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -104,6 +104,7 @@ struct Settings bool gpu_pgxp_texture_correction = true; bool gpu_pgxp_vertex_cache = false; bool gpu_pgxp_cpu = false; + bool gpu_pgxp_preserve_proj_fp = false; DisplayCropMode display_crop_mode = DisplayCropMode::None; s16 display_active_start_offset = 0; s16 display_active_end_offset = 0; diff --git a/src/duckstation-qt/advancedsettingswidget.cpp b/src/duckstation-qt/advancedsettingswidget.cpp index 518b505bd..e31d36048 100644 --- a/src/duckstation-qt/advancedsettingswidget.cpp +++ b/src/duckstation-qt/advancedsettingswidget.cpp @@ -85,6 +85,8 @@ AdvancedSettingsWidget::AdvancedSettingsWidget(QtHostInterface* host_interface, addBooleanTweakOption(m_host_interface, m_ui.tweakOptionTable, tr("PGXP Vertex Cache"), "GPU", "PGXPVertexCache", false); addBooleanTweakOption(m_host_interface, m_ui.tweakOptionTable, tr("PGXP CPU Mode"), "GPU", "PGXPCPU", false); + addBooleanTweakOption(m_host_interface, m_ui.tweakOptionTable, tr("PGXP Preserve Projection Precision"), "GPU", + "PGXPPreserveProjFP", false); addBooleanTweakOption(m_host_interface, m_ui.tweakOptionTable, tr("Enable Recompiler Memory Exceptions"), "CPU", "RecompilerMemoryExceptions", false); diff --git a/src/duckstation-sdl/sdl_host_interface.cpp b/src/duckstation-sdl/sdl_host_interface.cpp index 555e2a8e1..fdacf579d 100644 --- a/src/duckstation-sdl/sdl_host_interface.cpp +++ b/src/duckstation-sdl/sdl_host_interface.cpp @@ -959,6 +959,9 @@ void SDLHostInterface::DrawQuickSettingsMenu() m_settings_copy.gpu_pgxp_enable); settings_changed |= ImGui::MenuItem("PGXP CPU Instructions", nullptr, &m_settings_copy.gpu_pgxp_cpu, m_settings_copy.gpu_pgxp_enable); + settings_changed |= + ImGui::MenuItem("PGXP Preserve Projection Precision", nullptr, &m_settings_copy.gpu_pgxp_preserve_proj_fp, + m_settings_copy.gpu_pgxp_enable); ImGui::EndMenu(); }