diff --git a/src/core/fullscreen_ui.cpp b/src/core/fullscreen_ui.cpp index 81c9b2800..d0a57b8c8 100644 --- a/src/core/fullscreen_ui.cpp +++ b/src/core/fullscreen_ui.cpp @@ -4165,8 +4165,9 @@ void FullscreenUI::DrawDisplaySettingsPage() bsi->GetOptionalSmallStringValue("GPU", "Adapter", game_settings ? std::nullopt : std::optional("")); if (MenuButtonWithValue(FSUI_CSTR("GPU Adapter"), FSUI_CSTR("Selects the GPU to use for rendering."), - current_adapter.has_value() ? (current_adapter->empty() ? FSUI_CSTR("Default") : current_adapter->c_str()) : - FSUI_CSTR("Use Global Setting"))) + current_adapter.has_value() ? + (current_adapter->empty() ? FSUI_CSTR("Default") : current_adapter->c_str()) : + FSUI_CSTR("Use Global Setting"))) { ImGuiFullscreen::ChoiceDialogOptions options; options.reserve(s_graphics_adapter_list_cache.size() + 2); @@ -4203,8 +4204,8 @@ void FullscreenUI::DrawDisplaySettingsPage() OpenChoiceDialog(FSUI_ICONSTR(ICON_FA_TV, "GPU Adapter"), false, std::move(options), std::move(callback)); } - std::optional strvalue = bsi->GetOptionalSmallStringValue("GPU", "FullscreenMode", - game_settings ? std::nullopt : std::optional("")); + std::optional strvalue = bsi->GetOptionalSmallStringValue( + "GPU", "FullscreenMode", game_settings ? std::nullopt : std::optional("")); if (MenuButtonWithValue( FSUI_CSTR("Fullscreen Resolution"), FSUI_CSTR("Selects the resolution to use in fullscreen modes."), @@ -5152,6 +5153,10 @@ void FullscreenUI::DrawAdvancedSettingsPage() DrawToggleSetting(bsi, FSUI_CSTR("Enable PGXP Vertex Cache"), FSUI_CSTR("Uses screen positions to resolve PGXP data. May improve visuals in some games."), "GPU", "PGXPVertexCache", pgxp_enabled); + DrawToggleSetting(bsi, FSUI_CSTR("Disable PGXP on 2D Polygons"), + FSUI_CSTR("Uses native resolution coordinates for 2D polygons, instead of precise coordinates. Can " + "fix misaligned UI in some games, but otherwise should be left disabled."), + "GPU", "PGXPDisableOn2DPolygons", false, pgxp_enabled); DrawFloatRangeSetting( bsi, FSUI_CSTR("PGXP Geometry Tolerance"), FSUI_CSTR("Sets a threshold for discarding precise values when exceeded. May help with glitches in some games."), @@ -7354,6 +7359,7 @@ TRANSLATE_NOOP("FullscreenUI", "Device Settings"); TRANSLATE_NOOP("FullscreenUI", "Disable All Enhancements"); TRANSLATE_NOOP("FullscreenUI", "Disable Interlacing"); TRANSLATE_NOOP("FullscreenUI", "Disable Mailbox Presentation"); +TRANSLATE_NOOP("FullscreenUI", "Disable PGXP on 2D Polygons"); TRANSLATE_NOOP("FullscreenUI", "Disable Subdirectory Scanning"); TRANSLATE_NOOP("FullscreenUI", "Disabled"); TRANSLATE_NOOP("FullscreenUI", "Disables dithering and uses the full 8 bits per channel of color information."); @@ -7793,6 +7799,7 @@ TRANSLATE_NOOP("FullscreenUI", "Uses a blit presentation model instead of flippi TRANSLATE_NOOP("FullscreenUI", "Uses a light coloured theme instead of the default dark theme."); TRANSLATE_NOOP("FullscreenUI", "Uses a second thread for drawing graphics. Speed boost, and safe to use."); TRANSLATE_NOOP("FullscreenUI", "Uses game-specific settings for controllers for this game."); +TRANSLATE_NOOP("FullscreenUI", "Uses native resolution coordinates for 2D polygons, instead of precise coordinates. Can fix misaligned UI in some games, but otherwise should be left disabled."); TRANSLATE_NOOP("FullscreenUI", "Uses perspective-correct interpolation for colors, which can improve visuals in some games."); TRANSLATE_NOOP("FullscreenUI", "Uses perspective-correct interpolation for texture coordinates, straightening out warped textures."); TRANSLATE_NOOP("FullscreenUI", "Uses screen positions to resolve PGXP data. May improve visuals in some games."); diff --git a/src/core/game_database.cpp b/src/core/game_database.cpp index 484977769..36383bfa0 100644 --- a/src/core/game_database.cpp +++ b/src/core/game_database.cpp @@ -34,7 +34,7 @@ namespace GameDatabase { enum : u32 { GAME_DATABASE_CACHE_SIGNATURE = 0x45434C48, - GAME_DATABASE_CACHE_VERSION = 9, + GAME_DATABASE_CACHE_VERSION = 10, }; static Entry* GetMutableEntry(std::string_view serial); @@ -77,6 +77,7 @@ static constexpr const std::array(GameDatabase::Tr "DisablePGXPColorCorrection", "DisablePGXPDepthBuffer", "DisablePGXPPreserveProjFP", + "DisablePGXPOn2DPolygons", "ForcePGXPVertexCache", "ForcePGXPCPUMode", "ForceRecompilerMemoryExceptions", @@ -103,6 +104,7 @@ static constexpr const std::array(GameDatabase::Tr TRANSLATE_NOOP("GameDatabase", "Disable PGXP Color Correction"), TRANSLATE_NOOP("GameDatabase", "Disable PGXP Depth Buffer"), TRANSLATE_NOOP("GameDatabase", "Disable PGXP Preserve Projection Floating Point"), + TRANSLATE_NOOP("GameDatabase", "Disable PGXP on 2D Polygons"), TRANSLATE_NOOP("GameDatabase", "Force PGXP Vertex Cache"), TRANSLATE_NOOP("GameDatabase", "Force PGXP CPU Mode"), TRANSLATE_NOOP("GameDatabase", "Force Recompiler Memory Exceptions"), @@ -600,7 +602,7 @@ void GameDatabase::Entry::ApplySettings(Settings& settings, bool display_osd_mes osd_duration); } - settings.gpu_pgxp_vertex_cache = true; + settings.gpu_pgxp_vertex_cache = settings.gpu_pgxp_enable; } else if (settings.gpu_pgxp_enable && settings.gpu_pgxp_vertex_cache) { @@ -629,7 +631,7 @@ void GameDatabase::Entry::ApplySettings(Settings& settings, bool display_osd_mes #endif } - settings.gpu_pgxp_cpu = true; + settings.gpu_pgxp_cpu = settings.gpu_pgxp_enable; } else if (settings.UsingPGXPCPUMode()) { @@ -652,6 +654,17 @@ void GameDatabase::Entry::ApplySettings(Settings& settings, bool display_osd_mes settings.gpu_pgxp_depth_buffer = false; } + if (HasTrait(Trait::DisablePGXPOn2DPolygons)) + { + if (display_osd_messages && settings.gpu_pgxp_enable && !settings.gpu_pgxp_disable_2d) + { + Host::AddIconOSDMessage("gamedb_disable_pgxp_2d", ICON_FA_MICROCHIP, + TRANSLATE_STR("OSDMessage", "PGXP disabled on 2D polygons by compatibility settings."), + osd_duration); + } + g_settings.gpu_pgxp_disable_2d = true; + } + if (HasTrait(Trait::ForceRecompilerMemoryExceptions)) { WARNING_LOG("Memory exceptions for recompiler forced by compatibility settings."); diff --git a/src/core/game_database.h b/src/core/game_database.h index 06a2b0894..5f882ad77 100644 --- a/src/core/game_database.h +++ b/src/core/game_database.h @@ -45,6 +45,7 @@ enum class Trait : u32 DisablePGXPColorCorrection, DisablePGXPDepthBuffer, DisablePGXPPreserveProjFP, + DisablePGXPOn2DPolygons, ForcePGXPVertexCache, ForcePGXPCPUMode, ForceRecompilerMemoryExceptions, diff --git a/src/core/gpu_hw.cpp b/src/core/gpu_hw.cpp index fdad424fb..6fd95958a 100644 --- a/src/core/gpu_hw.cpp +++ b/src/core/gpu_hw.cpp @@ -2190,8 +2190,22 @@ void GPU_HW::LoadVertices() if (!valid_w) { SetBatchDepthBuffer(false); - for (BatchVertex& v : vertices) - v.w = 1.0f; + if (g_settings.gpu_pgxp_disable_2d) + { + // NOTE: This reads uninitialized data, but it's okay, it doesn't get used. + for (size_t i = 0; i < vertices.size(); i++) + { + BatchVertex& v = vertices[i]; + v.x = static_cast(native_vertex_positions[i].x); + v.y = static_cast(native_vertex_positions[i].y); + v.w = 1.0f; + } + } + else + { + for (BatchVertex& v : vertices) + v.w = 1.0f; + } } else if (m_pgxp_depth_buffer) { diff --git a/src/core/settings.cpp b/src/core/settings.cpp index af6107d55..fa9275092 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -203,7 +203,8 @@ void Settings::Load(SettingsInterface& si) si.GetStringValue("GPU", "TextureFilter", GetTextureFilterName(DEFAULT_GPU_TEXTURE_FILTER)).c_str()) .value_or(DEFAULT_GPU_TEXTURE_FILTER); gpu_sprite_texture_filter = - ParseTextureFilterName(si.GetStringValue("GPU", "SpriteTextureFilter", GetTextureFilterName(gpu_texture_filter)).c_str()) + ParseTextureFilterName( + si.GetStringValue("GPU", "SpriteTextureFilter", GetTextureFilterName(gpu_texture_filter)).c_str()) .value_or(gpu_texture_filter); gpu_line_detect_mode = ParseLineDetectModeName( @@ -231,6 +232,7 @@ void Settings::Load(SettingsInterface& si) gpu_pgxp_preserve_proj_fp = si.GetBoolValue("GPU", "PGXPPreserveProjFP", false); gpu_pgxp_tolerance = si.GetFloatValue("GPU", "PGXPTolerance", -1.0f); gpu_pgxp_depth_buffer = si.GetBoolValue("GPU", "PGXPDepthBuffer", false); + gpu_pgxp_disable_2d = si.GetBoolValue("GPU", "PGXPDisableOn2DPolygons", false); SetPGXPDepthClearThreshold(si.GetFloatValue("GPU", "PGXPDepthClearThreshold", DEFAULT_GPU_PGXP_DEPTH_THRESHOLD)); display_deinterlacing_mode = @@ -521,6 +523,7 @@ void Settings::Save(SettingsInterface& si, bool ignore_base) const si.SetBoolValue("GPU", "PGXPPreserveProjFP", gpu_pgxp_preserve_proj_fp); si.SetFloatValue("GPU", "PGXPTolerance", gpu_pgxp_tolerance); si.SetBoolValue("GPU", "PGXPDepthBuffer", gpu_pgxp_depth_buffer); + si.SetBoolValue("GPU", "PGXPDisableOn2DPolygons", gpu_pgxp_disable_2d); si.SetFloatValue("GPU", "PGXPDepthClearThreshold", GetPGXPDepthClearThreshold()); si.SetStringValue("Display", "DeinterlacingMode", GetDisplayDeinterlacingModeName(display_deinterlacing_mode)); @@ -749,6 +752,17 @@ void Settings::FixIncompatibleSettings(bool display_osd_messages) g_settings.gpu_pgxp_enable = false; } } + else + { + g_settings.gpu_pgxp_culling = false; + g_settings.gpu_pgxp_texture_correction = false; + g_settings.gpu_pgxp_color_correction = false; + g_settings.gpu_pgxp_vertex_cache = false; + g_settings.gpu_pgxp_cpu = false; + g_settings.gpu_pgxp_preserve_proj_fp = false; + g_settings.gpu_pgxp_depth_buffer = false; + g_settings.gpu_pgxp_disable_2d = false; + } #ifndef ENABLE_MMAP_FASTMEM if (g_settings.cpu_fastmem_mode == CPUFastmemMode::MMap) diff --git a/src/core/settings.h b/src/core/settings.h index 6b5729870..401e968aa 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -135,6 +135,7 @@ struct Settings bool gpu_pgxp_cpu : 1 = false; bool gpu_pgxp_preserve_proj_fp : 1 = false; bool gpu_pgxp_depth_buffer : 1 = false; + bool gpu_pgxp_disable_2d : 1 = false; DisplayDeinterlacingMode display_deinterlacing_mode = DEFAULT_DISPLAY_DEINTERLACING_MODE; DisplayCropMode display_crop_mode = DEFAULT_DISPLAY_CROP_MODE; DisplayAspectRatio display_aspect_ratio = DEFAULT_DISPLAY_ASPECT_RATIO; diff --git a/src/duckstation-qt/graphicssettingswidget.cpp b/src/duckstation-qt/graphicssettingswidget.cpp index 83b116328..09606ba38 100644 --- a/src/duckstation-qt/graphicssettingswidget.cpp +++ b/src/duckstation-qt/graphicssettingswidget.cpp @@ -133,6 +133,8 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget* SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.pgxpPreserveProjPrecision, "GPU", "PGXPPreserveProjFP", false); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.pgxpCPU, "GPU", "PGXPCPU", false); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.pgxpVertexCache, "GPU", "PGXPVertexCache", false); + SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.pgxpDisableOn2DPolygons, "GPU", "PGXPDisableOn2DPolygons", + false); connect(m_ui.pgxpTextureCorrection, &QCheckBox::checkStateChanged, this, &GraphicsSettingsWidget::updatePGXPSettingsEnabled); @@ -388,6 +390,10 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget* m_ui.pgxpVertexCache, tr("Vertex Cache"), tr("Unchecked"), tr("Uses screen-space vertex positions to obtain precise positions, instead of tracking memory accesses. Can " "provide PGXP compatibility for some games, but generally provides no benefit.")); + dialog->registerWidgetHelp(m_ui.pgxpDisableOn2DPolygons, tr("Disable on 2D Polygons"), tr("Unchecked"), + tr("Uses native resolution coordinates for 2D polygons, instead of precise coordinates. " + "Can fix misaligned UI in some games, but otherwise should be left disabled. The game " + "database will enable this automatically when needed.")); // OSD Tab diff --git a/src/duckstation-qt/graphicssettingswidget.ui b/src/duckstation-qt/graphicssettingswidget.ui index 1985adeb1..662f9a1db 100644 --- a/src/duckstation-qt/graphicssettingswidget.ui +++ b/src/duckstation-qt/graphicssettingswidget.ui @@ -525,13 +525,6 @@ - - - - Perspective Correct Textures - - - @@ -539,17 +532,17 @@ - - + + - Culling Correction + Vertex Cache - - + + - Preserve Projection Precision + Perspective Correct Textures @@ -560,10 +553,24 @@ - - + + - Vertex Cache + Preserve Projection Precision + + + + + + + Culling Correction + + + + + + + Disable on 2D Polygons