diff --git a/pcsx2-qt/Settings/GraphicsSettingsWidget.cpp b/pcsx2-qt/Settings/GraphicsSettingsWidget.cpp index 57409e48d1..5ea48928b4 100644 --- a/pcsx2-qt/Settings/GraphicsSettingsWidget.cpp +++ b/pcsx2-qt/Settings/GraphicsSettingsWidget.cpp @@ -263,6 +263,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* settings_dialog, SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_advanced.spinGPUDuringReadbacks, "EmuCore/GS", "HWSpinGPUForReadbacks", false); SettingWidgetBinder::BindWidgetToIntSetting(sif, m_advanced.texturePreloading, "EmuCore/GS", "texture_preloading", static_cast(TexturePreloadingLevel::Off)); + connect(m_advanced.texturePreloading, &QComboBox::currentIndexChanged, this, &GraphicsSettingsWidget::onTexturePreloadingChanged); setTabVisible(m_advanced_tab, QtHost::ShouldShowAdvancedSettings()); ////////////////////////////////////////////////////////////////////////// @@ -1080,6 +1081,22 @@ void GraphicsSettingsWidget::onCPUSpriteRenderBWChanged() m_fixes.cpuSpriteRenderLevel->setEnabled(value != 0); } +void GraphicsSettingsWidget::onTexturePreloadingChanged() +{ + // Loading and dumping textures only works with hash cache. + const bool texture_preloading_full = dialog()->getEffectiveIntValue("EmuCore/GS", "texture_preloading", 2) == 2; + const bool texture_replacements_enabled = m_texture.loadTextureReplacements->isChecked(); + const bool texture_dumping_enabled = m_texture.dumpReplaceableTextures->isChecked(); + + m_texture.loadTextureReplacements->setEnabled(texture_preloading_full); + m_texture.loadTextureReplacementsAsync->setEnabled(texture_preloading_full && texture_replacements_enabled); + m_texture.precacheTextureReplacements->setEnabled(texture_preloading_full && texture_replacements_enabled); + + m_texture.dumpReplaceableTextures->setEnabled(texture_preloading_full); + m_texture.dumpReplaceableMipmaps->setEnabled(texture_preloading_full && texture_dumping_enabled); + m_texture.dumpTexturesWithFMVActive->setEnabled(texture_preloading_full && texture_dumping_enabled); +} + GSRendererType GraphicsSettingsWidget::getEffectiveRenderer() const { const GSRendererType type = diff --git a/pcsx2-qt/Settings/GraphicsSettingsWidget.h b/pcsx2-qt/Settings/GraphicsSettingsWidget.h index 1dcfba7b89..42f29793fe 100644 --- a/pcsx2-qt/Settings/GraphicsSettingsWidget.h +++ b/pcsx2-qt/Settings/GraphicsSettingsWidget.h @@ -55,6 +55,7 @@ private Q_SLOTS: void onEnableAudioCaptureChanged(); void onEnableAudioCaptureArgumentsChanged(); void onOsdShowSettingsToggled(); + void onTexturePreloadingChanged(); private: GSRendererType getEffectiveRenderer() const; diff --git a/pcsx2/GameDatabase.cpp b/pcsx2/GameDatabase.cpp index b90c4ad5ce..94d9077db7 100644 --- a/pcsx2/GameDatabase.cpp +++ b/pcsx2/GameDatabase.cpp @@ -939,6 +939,26 @@ void GameDatabaseSchema::GameEntry::applyGSHardwareFixes(Pcsx2Config::GSOptions& } } +std::optional GameDatabaseSchema::GameEntry::getSpeedHackValue(const SpeedHack queried_speed_hack) const +{ + for (const auto& speed_hack : speedHacks) + { + if (speed_hack.first == queried_speed_hack) + return speed_hack.second; + } + return std::nullopt; +} + +std::optional GameDatabaseSchema::GameEntry::getGSHWFixValue(const GSHWFixId queried_hardware_fix) const +{ + for (const auto& hardware_fix : gsHWFixes) + { + if (hardware_fix.first == queried_hardware_fix) + return hardware_fix.second; + } + return std::nullopt; +} + void GameDatabase::initDatabase() { const std::string path(Path::Combine(EmuFolders::Resources, GAMEDB_YAML_FILE_NAME)); diff --git a/pcsx2/GameDatabase.h b/pcsx2/GameDatabase.h index 19d4790359..e203695701 100644 --- a/pcsx2/GameDatabase.h +++ b/pcsx2/GameDatabase.h @@ -101,7 +101,7 @@ namespace GameDatabaseSchema ClampMode vu0ClampMode = ClampMode::Undefined; ClampMode vu1ClampMode = ClampMode::Undefined; std::vector gameFixes; - std::vector> speedHacks; + std::vector> speedHacks; std::vector> gsHWFixes; std::vector memcardFilters; std::unordered_map patches; @@ -120,6 +120,12 @@ namespace GameDatabaseSchema /// Returns true if the current config value for the specified hw fix id matches the value. static bool configMatchesHWFix(const Pcsx2Config::GSOptions& config, GSHWFixId id, int value); + + /// Returns the value for a speed hack if the corresponding child exists in the DB. + std::optional getSpeedHackValue(const SpeedHack queried_speed_hack) const; + + /// Returns the value for a GS hardware fix if the corresponding child exists in the DB. + std::optional getGSHWFixValue(const GSHWFixId queried_hardware_fix) const; }; }; // namespace GameDatabaseSchema diff --git a/pcsx2/ImGui/FullscreenUI.cpp b/pcsx2/ImGui/FullscreenUI.cpp index 62742acdde..ab5f4965c7 100644 --- a/pcsx2/ImGui/FullscreenUI.cpp +++ b/pcsx2/ImGui/FullscreenUI.cpp @@ -4679,12 +4679,13 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad if (is_hardware) { - const bool dumping_active = GetEffectiveBoolSetting(bsi, "EmuCore/GS", "DumpReplaceableTextures", false); - const bool replacement_active = GetEffectiveBoolSetting(bsi, "EmuCore/GS", "LoadTextureReplacements", false); + const bool texture_preloading_full = GetEffectiveIntSetting(bsi, "EmuCore/GS", "texture_preloading", 2) == 2; + const bool dumping_active = GetEffectiveBoolSetting(bsi, "EmuCore/GS", "DumpReplaceableTextures", false) && texture_preloading_full; + const bool replacement_active = GetEffectiveBoolSetting(bsi, "EmuCore/GS", "LoadTextureReplacements", false) && texture_preloading_full; MenuHeading(FSUI_CSTR("Texture Replacement")); DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_IMAGES, "Load Textures"), FSUI_CSTR("Loads replacement textures where available and user-provided."), - "EmuCore/GS", "LoadTextureReplacements", false); + "EmuCore/GS", "LoadTextureReplacements", false, texture_preloading_full); DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_SPINNER, "Asynchronous Texture Loading"), FSUI_CSTR("Loads replacement textures on a worker thread, reducing microstutter when replacements are enabled."), "EmuCore/GS", "LoadTextureReplacementsAsync", true, replacement_active); @@ -4699,7 +4700,7 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad MenuHeading(FSUI_CSTR("Texture Dumping")); DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_DOWNLOAD, "Dump Textures"), FSUI_CSTR("Dumps replaceable textures to disk. Will reduce performance."), - "EmuCore/GS", "DumpReplaceableTextures", false); + "EmuCore/GS", "DumpReplaceableTextures", false, texture_preloading_full); DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_IMAGES, "Dump Mipmaps"), FSUI_CSTR("Includes mipmaps when dumping textures."), "EmuCore/GS", "DumpReplaceableMipmaps", false, dumping_active); DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_VIDEO, "Dump FMV Textures"), diff --git a/pcsx2/VMManager.cpp b/pcsx2/VMManager.cpp index 12153807f0..aad0aee8b5 100644 --- a/pcsx2/VMManager.cpp +++ b/pcsx2/VMManager.cpp @@ -3137,8 +3137,7 @@ void VMManager::WarnAboutUnsafeSettings() TRANSLATE_SV("VMManager", "Cycle rate/skip is not at default, this may crash or make games run too slow.")); } - const bool is_sw_renderer = EmuConfig.GS.Renderer == GSRendererType::SW; - if (!is_sw_renderer) + if (EmuConfig.GS.Renderer != GSRendererType::SW && EmuConfig.GS.Renderer != GSRendererType::Null) { // HW renderer settings. if (EmuConfig.GS.UpscaleMultiplier < 1.0f) @@ -3166,21 +3165,75 @@ void VMManager::WarnAboutUnsafeSettings() append(ICON_FA_CIRCLE_EXCLAMATION, TRANSLATE_SV("VMManager", "GPU Palette Conversion is enabled, this may reduce performance.")); } - if (EmuConfig.GS.TexturePreloading != TexturePreloadingLevel::Full) + + // Check if texturePreloading None or Partial in DB; assume Full if unspecified or game fixes are disabled. + s32 texture_preloading_DB_value = 2; + if (EmuConfig.EnableGameFixes) + { + if (const GameDatabaseSchema::GameEntry* game = GameDatabase::findGame(s_disc_serial)) + texture_preloading_DB_value = game->getGSHWFixValue(GameDatabaseSchema::GSHWFixId::TexturePreloading).value_or(2); + } + + if (EmuConfig.GS.TexturePreloading != TexturePreloadingLevel::Full || texture_preloading_DB_value != 2) + { + // No need to warn the user about performance for a setting we're enforcing. + if (texture_preloading_DB_value == 2) + { + append(ICON_FA_CIRCLE_EXCLAMATION, + TRANSLATE_SV("VMManager", "Texture Preloading is not set to Full. This may reduce performance.")); + } + else if (EmuConfig.GS.LoadTextureReplacements || EmuConfig.GS.DumpReplaceableTextures) + { + const std::string_view texture_preloading_DB_value_name = + (texture_preloading_DB_value == 0) ? + TRANSLATE_SV("VMManager", "None") : + TRANSLATE_SV("VMManager", "Partial"); + + if (EmuConfig.GS.TexturePreloading == TexturePreloadingLevel::Full) + { + append(ICON_FA_CIRCLE_EXCLAMATION, + fmt::format(TRANSLATE_FS("VMManager", "Texture Preloading is set to {} by the GameDB."), + texture_preloading_DB_value_name)); + } + else + { + const std::string_view texture_preloading_setting_value_name = + (EmuConfig.GS.TexturePreloading == TexturePreloadingLevel::Off) ? + TRANSLATE_SV("VMManager", "None") : + TRANSLATE_SV("VMManager", "Partial"); + append(ICON_FA_CIRCLE_EXCLAMATION, + fmt::format(TRANSLATE_FS("VMManager", "Texture Preloading is set to {} by the GameDB and to {} in the settings."), + texture_preloading_DB_value_name, texture_preloading_setting_value_name)); + } + } + + if (EmuConfig.GS.LoadTextureReplacements && EmuConfig.GS.DumpReplaceableTextures) + { + append(ICON_FA_IMAGES, + TRANSLATE_SV("VMManager", "Texture replacement and dumping will not work unless Texture Preloading is set to Full.")); + } + else if (EmuConfig.GS.LoadTextureReplacements) + { + append(ICON_FA_IMAGES, + TRANSLATE_SV("VMManager", "Texture replacement will not work unless Texture Preloading is set to Full.")); + } + else if (EmuConfig.GS.DumpReplaceableTextures) + { + append(ICON_FA_DOWNLOAD, + TRANSLATE_SV("VMManager", "Texture dumping will not work unless Texture Preloading is set to Full.")); + } + } + // No textures dumped while texture preloading isn't set to Full. + else if (EmuConfig.GS.DumpReplaceableTextures) { append(ICON_FA_CIRCLE_EXCLAMATION, - TRANSLATE_SV("VMManager", "Texture Preloading is not Full, this may reduce performance.")); + TRANSLATE_SV("VMManager", "Texture dumping is enabled. This will continually dump textures to disk.")); } if (EmuConfig.GS.UserHacks_EstimateTextureRegion) { append(ICON_FA_CIRCLE_EXCLAMATION, TRANSLATE_SV("VMManager", "Estimate texture region is enabled, this may reduce performance.")); } - if (EmuConfig.GS.DumpReplaceableTextures) - { - append(ICON_FA_CIRCLE_EXCLAMATION, - TRANSLATE_SV("VMManager", "Texture dumping is enabled, this will continually dump textures to disk.")); - } if (!EmuConfig.GS.HWMipmap) { append(ICON_FA_IMAGES,