diff --git a/.ci/android/build.sh b/.ci/android/build.sh index 836faa38d5..4b4c9c0834 100755 --- a/.ci/android/build.sh +++ b/.ci/android/build.sh @@ -13,8 +13,8 @@ fi cd src/android chmod +x ./gradlew -./gradlew assembleMainlineRelease -./gradlew bundleMainlineRelease +./gradlew assembleRelease +./gradlew bundleRelease if [ ! -z "${ANDROID_KEYSTORE_B64}" ]; then rm "${ANDROID_KEYSTORE_FILE}" diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b69782a23..f436c0a183 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -287,13 +287,6 @@ if (ANDROID) set(CMAKE_POLICY_VERSION_MINIMUM 3.5) # Workaround for Oboe endif() -# We need to downgrade debug info (/Zi -> /Z7) to use an older but more cacheable format -# See https://github.com/nanoant/CMakePCHCompiler/issues/21 -if(WIN32 AND (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")) - string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") - string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") -endif() - # Default to a Release build get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) if (NOT IS_MULTI_CONFIG AND NOT CMAKE_BUILD_TYPE) diff --git a/docs/User.md b/docs/User.md index 67f81eadb6..ba5d1b3eb0 100644 --- a/docs/User.md +++ b/docs/User.md @@ -7,4 +7,4 @@ This handbook is primarily aimed at the end-user - baking useful knowledge for e - **[The Basics](user/Basics.md)** - **[Audio](user/Audio.md)** - **[Graphics](user/Graphics.md)** -- **[Platforms and Architectures](user/Architectures.md)** +- **[Platforms and Architectures](user/Architectures.md)** \ No newline at end of file diff --git a/docs/build/Android.md b/docs/build/Android.md index f511f71370..c8ff3a3b1e 100644 --- a/docs/build/Android.md +++ b/docs/build/Android.md @@ -33,7 +33,6 @@ Eden by default will be cloned into - 4. Navigate to `eden/src/android`. 5. Then Build with `./gradlew assembleRelWithDebInfo`. 6. To build the optimised build use `./gradlew assembleGenshinSpoofRelWithDebInfo`. -7. You can pass extra variables to cmake via `-PYUZU_ANDROID_ARGS="-D..."` ### Script A convenience script for building is provided in `.ci/android/build.sh`. The built APK can be put into an `artifacts` directory via `.ci/android/package.sh`. On Windows, these must be done in the Git Bash or MinGW terminal. diff --git a/docs/user/Architectures.md b/docs/user/Architectures.md index 240feb666d..6d60716684 100644 --- a/docs/user/Architectures.md +++ b/docs/user/Architectures.md @@ -63,8 +63,6 @@ While all modern Linux distributions are supported (Fedora >40, Ubuntu >24.04, D Intel and Nvidia GPU support is limited. AMD (RADV) drivers receive first-class testing and are known to provide the most stable Eden experience possible. -Wayland is not recommended. Testing has shown significantly worse performance on most Wayland compositors compared to X11, alongside mysterious bugs and compatibility errors. For now, set `QT_QPA_PLATFORM=xcb` when running Eden, or pass `-platform xcb` to the launch arguments. - ## Windows Windows 10 and 11 are supported. Support for Windows 8.x is unknown, and Windows 7 support is unlikely to ever be added. diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index 2da461fd5c..434e6fb100 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -155,14 +155,12 @@ if (YUZU_USE_BUNDLED_SIRIT) AddJsonPackage(sirit-ci) else() AddJsonPackage(sirit) - # Change to old-but-more-cacheable debug info on Windows - if (WIN32 AND (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")) - get_target_property(sirit_opts sirit COMPILE_OPTIONS) - list(FILTER sirit_opts EXCLUDE REGEX "/Zi") - list(APPEND sirit_opts "/Z7") - set_target_properties(sirit PROPERTIES COMPILE_OPTIONS "${sirit_opts}") - endif() - if(MSVC AND CXX_CLANG) + if(MSVC AND USE_CCACHE AND sirit_ADDED) + get_target_property(_opts sirit COMPILE_OPTIONS) + list(FILTER _opts EXCLUDE REGEX "/Zi") + list(APPEND _opts "/Z7") + set_target_properties(siritobj PROPERTIES COMPILE_OPTIONS "${_opts}") + elseif(MSVC AND CXX_CLANG) target_compile_options(siritobj PRIVATE -Wno-error=unused-command-line-argument) endif() endif() diff --git a/externals/cpmfile.json b/externals/cpmfile.json index dde8c22d5f..aa3a97c128 100644 --- a/externals/cpmfile.json +++ b/externals/cpmfile.json @@ -117,9 +117,9 @@ }, "spirv-tools": { "package": "SPIRV-Tools", - "repo": "crueter/SPIRV-Tools", - "sha": "2fa2d44485", - "hash": "45b198be1d09974ccb2438e8bfa5683f23a0421b058297c28eacfd77e454ec2cf87e77850eddd202efff34b004d8d6b4d12e9615e59bd72be904c196f5eb2169", + "repo": "KhronosGroup/SPIRV-Tools", + "tag": "v%VERSION%", + "hash": "b17940433ced72e004c5eeffd7dd411b6afcc6a52ee31de6427d88edceb8172369be8ec8bf5b65708a78bf41fdae264d554aa7750b2209831679ab36bc867567", "git_version": "2025.4", "options": [ "SPIRV_SKIP_EXECUTABLES ON" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0f3c5cfd4b..88470c4c42 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -101,9 +101,15 @@ if (MSVC AND NOT CXX_CLANG) ) endif() - if (WIN32 AND (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")) - string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") - string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") + if (USE_CCACHE OR YUZU_USE_PRECOMPILED_HEADERS) + # when caching, we need to use /Z7 to downgrade debug info to use an older but more cacheable format + # Precompiled headers are deleted if not using /Z7. See https://github.com/nanoant/CMakePCHCompiler/issues/21 + add_compile_options(/Z7) + # Avoid D9025 warning + string(REPLACE "/Zi" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") + string(REPLACE "/Zi" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") + else() + add_compile_options(/Zi) endif() if (ARCHITECTURE_x86_64) diff --git a/src/android/app/build.gradle.kts b/src/android/app/build.gradle.kts index 31db36199a..c85da039cb 100644 --- a/src/android/app/build.gradle.kts +++ b/src/android/app/build.gradle.kts @@ -75,8 +75,6 @@ android { externalNativeBuild { cmake { - val extraCMakeArgs = (project.findProperty("YUZU_ANDROID_ARGS") as String?)?.split("\\s+".toRegex()) ?: emptyList() - arguments.addAll(listOf( "-DENABLE_QT=0", // Don't use QT "-DENABLE_SDL2=0", // Don't use SDL @@ -89,8 +87,7 @@ android { "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON", "-DBUILD_TESTING=OFF", "-DYUZU_TESTS=OFF", - "-DDYNARMIC_TESTS=OFF", - *extraCMakeArgs.toTypedArray() + "-DDYNARMIC_TESTS=OFF" )) abiFilters("arm64-v8a") diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt index b26fb1dec5..638e1101db 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt @@ -51,6 +51,7 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting { SOC_OVERLAY_BACKGROUND("soc_overlay_background"), + ENABLE_RAII("enable_raii"), FRAME_INTERPOLATION("frame_interpolation"), // FRAME_SKIPPING("frame_skipping"), @@ -70,6 +71,7 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting { DEBUG_FLUSH_BY_LINE("flush_line"), USE_LRU_CACHE("use_lru_cache"); + external fun isRaiiEnabled(): Boolean // external fun isFrameSkippingEnabled(): Boolean external fun isFrameInterpolationEnabled(): Boolean diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt index ebc726225a..5f7f7a43f9 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt @@ -229,6 +229,13 @@ abstract class SettingsItem( override fun reset() = BooleanSetting.USE_DOCKED_MODE.reset() } + put( + SwitchSetting( + BooleanSetting.ENABLE_RAII, + titleId = R.string.enable_raii, + descriptionId = R.string.enable_raii_description + ) + ) put( SwitchSetting( BooleanSetting.FRAME_INTERPOLATION, @@ -826,4 +833,3 @@ abstract class SettingsItem( } } } - diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt index 0d882a7f01..715baec72f 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt @@ -462,6 +462,7 @@ class SettingsFragmentPresenter( add(IntSetting.RENDERER_SAMPLE_SHADING_FRACTION.key) add(HeaderSetting(R.string.veil_renderer)) + add(BooleanSetting.ENABLE_RAII.key) add(BooleanSetting.RENDERER_EARLY_RELEASE_FENCES.key) add(IntSetting.DMA_ACCURACY.key) add(BooleanSetting.BUFFER_REORDER_DISABLE.key) diff --git a/src/android/app/src/main/res/values-ar/strings.xml b/src/android/app/src/main/res/values-ar/strings.xml index 388afd88cd..4b58d5f851 100644 --- a/src/android/app/src/main/res/values-ar/strings.xml +++ b/src/android/app/src/main/res/values-ar/strings.xml @@ -64,6 +64,8 @@ امتدادات GPU العارض + RAII + طريقة لإدارة الموارد تلقائيًا في فولكان تضمن الإفراج الصحيح عن الموارد عندما لا تكون هناك حاجة إليها، ولكن قد تسبب تعطل الألعاب المجمعة. وحدة المعالجة المركزية والذاكرة حجاب عدن إعدادات تجريبية لتحسين الأداء والقدرة. قد تسبب هذه الإعدادات شاشات سوداء أو مشاكل أخرى في اللعبة. diff --git a/src/android/app/src/main/res/values-ckb/strings.xml b/src/android/app/src/main/res/values-ckb/strings.xml index 2ab4af16ad..25fcf6acef 100644 --- a/src/android/app/src/main/res/values-ckb/strings.xml +++ b/src/android/app/src/main/res/values-ckb/strings.xml @@ -65,6 +65,8 @@ پاشکۆکانی GPU رێندرەر + RAII + ڕێگایەکی بەڕێوەبردنی سەرچاوەکان بە خۆکار لە ڤولکان کە دڵنیای دەکاتەوە لە ئازادکردنی گونجاوی سەرچاوەکان کاتێک کە چیتر پێویستیان نییە، بەڵام لەوانەیە ببێتە هۆی کەوتنی یارییە کۆکراوەکان. CPU و بیرگە حجاب عدن ڕێکخستنە تاقیکارییەکان بۆ باشترکردنی کارایی و توانا. ئەم ڕێکخستنانە لەوانەیە ببێتە هۆی شاشە ڕەشەکان یان کێشەیتری یاری. diff --git a/src/android/app/src/main/res/values-cs/strings.xml b/src/android/app/src/main/res/values-cs/strings.xml index ad8f89ffc5..8d7e274464 100644 --- a/src/android/app/src/main/res/values-cs/strings.xml +++ b/src/android/app/src/main/res/values-cs/strings.xml @@ -64,6 +64,8 @@ Rozšíření GPU Renderer + RAII + Metoda automatické správy prostředků ve Vulkanu, která zajišťuje správné uvolnění prostředků, když již nejsou potřeba, ale může způsobit pády v balených hrách. CPU a paměť Edenův závoj Experimentální nastavení pro zlepšení výkonu a schopností. Tato nastavení mohou způsobit černé obrazovky nebo další herní problémy. diff --git a/src/android/app/src/main/res/values-de/strings.xml b/src/android/app/src/main/res/values-de/strings.xml index cf12a2244f..146fa60fed 100644 --- a/src/android/app/src/main/res/values-de/strings.xml +++ b/src/android/app/src/main/res/values-de/strings.xml @@ -65,6 +65,8 @@ GPU-Erweiterungen Renderer + RAII + Eine Methode zur automatischen Ressourcenverwaltung in Vulkan, die eine ordnungsgemäße Freigabe von Ressourcen gewährleistet, wenn sie nicht mehr benötigt werden, aber bei gebündelten Spielen Abstürze verursachen kann. CPU und Speicher Edens Schleier Experimentelle Einstellungen zur Verbesserung der Leistung und Funktionalität. Diese Einstellungen können schwarze Bildschirme oder andere Spielprobleme verursachen. diff --git a/src/android/app/src/main/res/values-es/strings.xml b/src/android/app/src/main/res/values-es/strings.xml index eff563b7ea..28a93f005b 100644 --- a/src/android/app/src/main/res/values-es/strings.xml +++ b/src/android/app/src/main/res/values-es/strings.xml @@ -65,6 +65,8 @@ Extensiones de GPU Renderizador + RAII + Un método de gestión automática de recursos en Vulkan que garantiza la liberación adecuada de recursos cuando ya no son necesarios, pero puede causar fallos en juegos empaquetados. CPU y memoria Velo de Edén Configuraciones experimentales para mejorar el rendimiento y la capacidad. Estas configuraciones pueden causar pantallas negras u otros problemas en el juego. diff --git a/src/android/app/src/main/res/values-fa/strings.xml b/src/android/app/src/main/res/values-fa/strings.xml index 205662b182..b30f67292a 100644 --- a/src/android/app/src/main/res/values-fa/strings.xml +++ b/src/android/app/src/main/res/values-fa/strings.xml @@ -65,6 +65,8 @@ افزونه‌های GPU رندرر + RAII + روشی برای مدیریت خودکار منابع در ولکان که تضمین می‌کند منابع به درستی آزاد شوند وقتی دیگر مورد نیاز نیستند، اما ممکن است باعث کرش شدن بازی‌های بسته‌بندی شده شود. پردازنده و حافظه پرده عدن تنظیمات آزمایشی برای بهبود عملکرد و قابلیت. این تنظیمات ممکن است باعث نمایش صفحه سیاه یا سایر مشکلات بازی شود. diff --git a/src/android/app/src/main/res/values-fr/strings.xml b/src/android/app/src/main/res/values-fr/strings.xml index 12c93fd76c..f4c741aecc 100644 --- a/src/android/app/src/main/res/values-fr/strings.xml +++ b/src/android/app/src/main/res/values-fr/strings.xml @@ -65,6 +65,8 @@ Extensions GPU Rendu + RAII + Une méthode de gestion automatique des ressources dans Vulkan qui assure la libération correcte des ressources lorsqu\'elles ne sont plus nécessaires, mais peut provoquer des plantages dans les jeux regroupés. CPU et mémoire Voile d\'Eden Paramètres expérimentaux pour améliorer les performances et les capacités. Ces paramètres peuvent causer des écrans noirs ou d\'autres problèmes de jeu. diff --git a/src/android/app/src/main/res/values-he/strings.xml b/src/android/app/src/main/res/values-he/strings.xml index 9efaf05085..6c5a877a66 100644 --- a/src/android/app/src/main/res/values-he/strings.xml +++ b/src/android/app/src/main/res/values-he/strings.xml @@ -65,6 +65,8 @@ הרחבות GPU רנדרר + RAII + שיטה לניהול אוטומטי של משאבים ב-Vulkan המבטיחה שחרור נכון של משאבים כאשר הם כבר לא נחוצים, אך עלולה לגרום לקריסות במשחקים מאוגדים. מעבד וזיכרון עדן וייל הגדרות ניסיוניות לשיפור ביצועים ויכולות. הגדרות אלו עלולות לגרום למסכים שחורים או לבעיות אחרות במשחק. diff --git a/src/android/app/src/main/res/values-hu/strings.xml b/src/android/app/src/main/res/values-hu/strings.xml index 20b222818f..6c4f428086 100644 --- a/src/android/app/src/main/res/values-hu/strings.xml +++ b/src/android/app/src/main/res/values-hu/strings.xml @@ -65,6 +65,8 @@ GPU kiterjesztések Megjelenítő + RAII + A Vulkan erőforrás-kezelési módszere, amely biztosítja az erőforrások megfelelő felszabadítását, ha már nincs rájuk szükség, de csomagolt játékok összeomlását okozhatja. CPU és memória Eden Fátyla Kísérleti beállítások a teljesítmény és képesség javításához. Ezek a beállítások fekete képernyőket vagy más játékproblémákat okozhatnak. diff --git a/src/android/app/src/main/res/values-id/strings.xml b/src/android/app/src/main/res/values-id/strings.xml index 83db153bec..8e89132815 100644 --- a/src/android/app/src/main/res/values-id/strings.xml +++ b/src/android/app/src/main/res/values-id/strings.xml @@ -65,6 +65,8 @@ Ekstensi GPU Renderer + RAII + Metode manajemen sumber daya otomatis di Vulkan yang memastikan pelepasan sumber daya yang tepat ketika tidak lagi diperlukan, tetapi dapat menyebabkan crash pada game yang dibundel. CPU dan Memori Eden\'s Veil Pengaturan eksperimental untuk meningkatkan kinerja dan kemampuan. Pengaturan ini dapat menyebabkan layar hitam atau masalah game lainnya. diff --git a/src/android/app/src/main/res/values-it/strings.xml b/src/android/app/src/main/res/values-it/strings.xml index 7d5c118441..339bae8883 100644 --- a/src/android/app/src/main/res/values-it/strings.xml +++ b/src/android/app/src/main/res/values-it/strings.xml @@ -65,6 +65,8 @@ Estensioni GPU Renderer + RAII + Un metodo di gestione automatica delle risorse in Vulkan che garantisce il corretto rilascio delle risorse quando non sono più necessarie, ma può causare crash nei giochi in bundle. CPU e Memoria Velo di Eden Impostazioni sperimentali per migliorare prestazioni e capacità. Queste impostazioni possono causare schermate nere o altri problemi di gioco. diff --git a/src/android/app/src/main/res/values-ja/strings.xml b/src/android/app/src/main/res/values-ja/strings.xml index 0d0c37c78f..4fc9f135e4 100644 --- a/src/android/app/src/main/res/values-ja/strings.xml +++ b/src/android/app/src/main/res/values-ja/strings.xml @@ -65,6 +65,8 @@ GPU拡張機能 レンダラー + RAII + Vulkanにおける自動リソース管理の方法で、不要になったリソースを適切に解放しますが、バンドルされたゲームでクラッシュを引き起こす可能性があります。 CPUとメモリ エデンのベール パフォーマンスと機能を向上させる実験的な設定。これらの設定は黒画面やその他のゲームの問題を引き起こす可能性があります。 diff --git a/src/android/app/src/main/res/values-ko/strings.xml b/src/android/app/src/main/res/values-ko/strings.xml index ff0af4fc43..ebad3409d7 100644 --- a/src/android/app/src/main/res/values-ko/strings.xml +++ b/src/android/app/src/main/res/values-ko/strings.xml @@ -65,6 +65,8 @@ GPU 확장 기능 렌더러 + RAII + Vulkan에서 자동 리소스 관리를 위한 방법으로, 더 이상 필요하지 않은 리소스를 적절히 해제하지만 번들된 게임에서 충돌을 일으킬 수 있습니다. CPU 및 메모리 에덴의 베일 성능 및 기능을 향상시키기 위한 실험적 설정. 이 설정은 검은 화면 또는 기타 게임 문제를 일으킬 수 있습니다. diff --git a/src/android/app/src/main/res/values-nb/strings.xml b/src/android/app/src/main/res/values-nb/strings.xml index 313d8797c3..4a5f6f2efb 100644 --- a/src/android/app/src/main/res/values-nb/strings.xml +++ b/src/android/app/src/main/res/values-nb/strings.xml @@ -65,6 +65,8 @@ GPU-utvidelser Renderer + RAII + En metode for automatisk ressurshåndtering i Vulkan som sikrer riktig frigjøring av ressurser når de ikke lenger trengs, men kan føre til krasj i bundlede spill. CPU og minne Edens slør Eksperimentelle innstillinger for å forbedre ytelse og funksjonalitet. Disse innstillingene kan forårsake svarte skjermer eller andre spillproblemer. diff --git a/src/android/app/src/main/res/values-pl/strings.xml b/src/android/app/src/main/res/values-pl/strings.xml index 4ebe24e1c9..d1bc789aa9 100644 --- a/src/android/app/src/main/res/values-pl/strings.xml +++ b/src/android/app/src/main/res/values-pl/strings.xml @@ -65,6 +65,8 @@ Rozszerzenia GPU Renderer + RAII + Metoda automatycznego zarządzania zasobami w Vulkanie, która zapewnia prawidłowe zwalnianie zasobów, gdy nie są już potrzebne, ale może powodować awarie w pakietowych grach. Procesor i pamięć Zasłona Edenu Eksperymentalne ustawienia poprawiające wydajność i możliwości. Te ustawienia mogą powodować czarne ekrany lub inne problemy z grą. diff --git a/src/android/app/src/main/res/values-pt-rBR/strings.xml b/src/android/app/src/main/res/values-pt-rBR/strings.xml index 2f5f4c4b5b..bad95a18e5 100644 --- a/src/android/app/src/main/res/values-pt-rBR/strings.xml +++ b/src/android/app/src/main/res/values-pt-rBR/strings.xml @@ -65,6 +65,8 @@ Extensões da GPU Renderizador + RAII + Um método de gerenciamento automático de recursos no Vulkan que garante a liberação adequada de recursos quando não são mais necessários, mas pode causar falhas em jogos empacotados. CPU e Memória Véu do Éden Configurações experimentais para melhorar desempenho e capacidade. Essas configurações podem causar telas pretas ou outros problemas no jogo. diff --git a/src/android/app/src/main/res/values-pt-rPT/strings.xml b/src/android/app/src/main/res/values-pt-rPT/strings.xml index 084fe1c82d..0b57eebab6 100644 --- a/src/android/app/src/main/res/values-pt-rPT/strings.xml +++ b/src/android/app/src/main/res/values-pt-rPT/strings.xml @@ -65,6 +65,8 @@ Extensões da GPU Renderizador + RAII + Um método de gestão automática de recursos no Vulkan que garante a libertação adequada de recursos quando já não são necessários, mas pode causar falhas em jogos empacotados. CPU e Memória Véu do Éden Definições experimentais para melhorar o desempenho e capacidade. Estas definições podem causar ecrãs pretos ou outros problemas no jogo. diff --git a/src/android/app/src/main/res/values-ru/strings.xml b/src/android/app/src/main/res/values-ru/strings.xml index 0938b9c18f..53f49b91cb 100644 --- a/src/android/app/src/main/res/values-ru/strings.xml +++ b/src/android/app/src/main/res/values-ru/strings.xml @@ -72,6 +72,8 @@ Настройки в Покров Эдема являются экспериментальными и могут вызывать проблемы. Если ваша игра не запускается, отключите все расширения. В разработке: Пропуск кадров Включите или отключите пропуск кадров для повышения производительности за счет уменьшения количества отображаемых кадров. Эта функция находится в разработке и будет включена в будущих версиях. + RAII + Метод автоматического управления ресурсами в Vulkan, который обеспечивает правильное освобождение ресурсов при их ненадобности, но может вызывать сбои в бандл-играх. Улучшенная синхронизация кадров Обеспечивает плавную и стабильную подачу кадров за счет синхронизации их времени, уменьшая подтормаживания и неравномерную анимацию. Идеально для игр с нестабильным временем кадров или микро-подтормаживаниями во время игры. Ранний релиз ограждений diff --git a/src/android/app/src/main/res/values-sr/strings.xml b/src/android/app/src/main/res/values-sr/strings.xml index 35ef07f3a6..3f2de72f8b 100644 --- a/src/android/app/src/main/res/values-sr/strings.xml +++ b/src/android/app/src/main/res/values-sr/strings.xml @@ -81,6 +81,8 @@ Побољшава текстуру и руковање међуспремника, као и преводилачки слој Маквелл. Подржани од стране неких Вулкана 1.1 ГПУ-а и сви Вулкан 1.2+ ГПУ. Рендерер + RAII + Метод аутоматског управљања ресурсима у Vulkan-у који осигурава правилно ослобађање ресурса када више нису потребни, али може изазвати падове у пакованим играма. Побољшани оквирни пејсинг Осигурава глатку и доследан испоруку оквира синхронизацијом времена између оквира, смањење муцања и неуједначене анимације. Идеално за игре које доживљавају временски оквир нестабилност или микро-штитнике током играња. Ranije oslobađanje ograda diff --git a/src/android/app/src/main/res/values-uk/strings.xml b/src/android/app/src/main/res/values-uk/strings.xml index b22c30999b..b5eee4992c 100644 --- a/src/android/app/src/main/res/values-uk/strings.xml +++ b/src/android/app/src/main/res/values-uk/strings.xml @@ -70,6 +70,8 @@ Експериментальні налаштування для покращення продуктивності та сумісності. Ці налаштування можуть викликати збої, зокрема чорний екран. Експериментальні налаштування Налаштування Завіси Eden є експериментальними та можуть спричинити проблеми. Якщо ваша гра не запускається — вимкніть усі розширення. + RAII + Метод автоматичного керування ресурсами у Vulkan, який забезпечує правильне звільнення ресурсів після завершення їх використання, проте він може спричинити збої в ігрових збірниках. В розробці: Пропуск кадрів Увімкніть або вимкніть пропуск кадрів для покращення продуктивності за рахунок зменшення кількості візуалізованих кадрів. Ця функція ще розробляється та буде доступна у майбутніх версіях. Покращена синхронізація кадрів diff --git a/src/android/app/src/main/res/values-vi/strings.xml b/src/android/app/src/main/res/values-vi/strings.xml index 171b4ea116..1a34509f5c 100644 --- a/src/android/app/src/main/res/values-vi/strings.xml +++ b/src/android/app/src/main/res/values-vi/strings.xml @@ -65,6 +65,8 @@ Tiện ích mở rộng GPU Trình kết xuất + RAII + Phương pháp quản lý tài nguyên tự động trong Vulkan đảm bảo giải phóng tài nguyên đúng cách khi không còn cần thiết, nhưng có thể gây ra sự cố trong các trò chơi được đóng gói. CPU và Bộ nhớ Mành che của Eden Cài đặt thử nghiệm để cải thiện hiệu suất và khả năng. Những cài đặt này có thể gây ra màn hình đen hoặc các vấn đề khác trong trò chơi. diff --git a/src/android/app/src/main/res/values-zh-rCN/strings.xml b/src/android/app/src/main/res/values-zh-rCN/strings.xml index daa2143beb..6fa40b8727 100644 --- a/src/android/app/src/main/res/values-zh-rCN/strings.xml +++ b/src/android/app/src/main/res/values-zh-rCN/strings.xml @@ -65,6 +65,8 @@ GPU扩展 渲染器 + RAII + Vulkan中的一种自动资源管理方法,确保在不再需要时正确释放资源,但可能导致捆绑游戏崩溃。 CPU和内存 伊甸之幕 实验性设置以提高性能和能力。这些设置可能会导致黑屏或其他游戏问题。 diff --git a/src/android/app/src/main/res/values-zh-rTW/strings.xml b/src/android/app/src/main/res/values-zh-rTW/strings.xml index 67f3f268a8..b73ec8ccaa 100644 --- a/src/android/app/src/main/res/values-zh-rTW/strings.xml +++ b/src/android/app/src/main/res/values-zh-rTW/strings.xml @@ -65,6 +65,8 @@ GPU擴充功能 渲染器 + RAII + Vulkan中的一種自動資源管理方法,確保在不再需要時正確釋放資源,但可能導致捆綁遊戲崩潰。 CPU與記憶體 伊甸之幕 實驗性設定以提高效能和能力。這些設定可能會導致黑屏或其他遊戲問題。 diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml index 2150d401db..1b66c191d3 100644 --- a/src/android/app/src/main/res/values/arrays.xml +++ b/src/android/app/src/main/res/values/arrays.xml @@ -180,7 +180,6 @@ @string/resolution_half @string/resolution_three_quarter @string/resolution_one - @string/resolution_five_quarter @string/resolution_three_half @string/resolution_two @string/resolution_three @@ -203,7 +202,6 @@ 5 6 7 - 8 @@ -253,16 +251,12 @@ @string/scaling_filter_nearest_neighbor @string/scaling_filter_bilinear @string/scaling_filter_bicubic + @string/scaling_filter_spline1 @string/scaling_filter_gaussian @string/scaling_filter_lanczos @string/scaling_filter_scale_force @string/scaling_filter_fsr @string/scaling_filter_area - @string/scaling_filter_mmpx - @string/scaling_filter_zero_tangent - @string/scaling_filter_bspline - @string/scaling_filter_mitchell - @string/scaling_filter_spline1 @@ -275,10 +269,6 @@ 6 7 8 - 9 - 10 - 11 - 12 diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 00206a5df5..2a5cc48bb1 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -109,6 +109,8 @@ The intensity of the sample shading pass. Higher values improve quality more but also reduce performance to a greater extent. Renderer + RAII + A method of automatic resource management in Vulkan that ensures proper release of resources when they are no longer needed, but may cause crashes in bundled games. Enhanced Frame Pacing Ensures smooth and consistent frame delivery by synchronizing the timing between frames, reducing stuttering and uneven animation. Ideal for games that experience frame timing instability or micro-stutters during gameplay. Release Fences Early @@ -994,7 +996,6 @@ 0.5X (360p/540p) 0.75X (540p/810p) 1X (720p/1080p) - 1.25X (900p/1350p) 1.5X (1080p/1620p) 2X (1440p/2160p) (Slow) 3X (2160p/3240p) (Slow) @@ -1016,10 +1017,6 @@ ScaleForce AMD FidelityFX™ Super Resolution Area - Zero-Tangent - B-Spline - Mitchell - MMPX None diff --git a/src/common/fs/fs_types.h b/src/common/fs/fs_types.h index 7b7359fa6f..900f85d24e 100644 --- a/src/common/fs/fs_types.h +++ b/src/common/fs/fs_types.h @@ -1,12 +1,8 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once -#include #include #include "common/common_funcs.h" diff --git a/src/common/settings.cpp b/src/common/settings.cpp index b849d7cb6a..b41f4c75f5 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -301,10 +301,6 @@ void TranslateResolutionInfo(ResolutionSetup setup, ResolutionScalingInfo& info) info.up_scale = 3; info.down_shift = 1; break; - case ResolutionSetup::Res5_4X: - info.up_scale = 5; - info.down_shift = 2; - break; case ResolutionSetup::Res2X: info.up_scale = 2; info.down_shift = 0; diff --git a/src/common/settings.h b/src/common/settings.h index dd9b03f28e..59e75d3ee0 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -161,7 +161,7 @@ struct Values { Category::LibraryApplet}; Setting photo_viewer_applet_mode{ linkage, AppletMode::LLE, "photo_viewer_applet_mode", Category::LibraryApplet}; - Setting offline_web_applet_mode{linkage, AppletMode::HLE, "offline_web_applet_mode", + Setting offline_web_applet_mode{linkage, AppletMode::LLE, "offline_web_applet_mode", Category::LibraryApplet}; Setting login_share_applet_mode{linkage, AppletMode::HLE, "login_share_applet_mode", Category::LibraryApplet}; @@ -336,6 +336,7 @@ struct Values { "shader_backend", Category::Renderer, Specialization::RuntimeList}; SwitchableSetting vulkan_device{linkage, 0, "vulkan_device", Category::Renderer, Specialization::RuntimeList}; + SwitchableSetting enable_raii{linkage, false, "enable_raii", Category::Renderer}; #ifdef __ANDROID__ SwitchableSetting frame_interpolation{linkage, true, "frame_interpolation", Category::Renderer, Specialization::RuntimeList}; diff --git a/src/common/settings_enums.h b/src/common/settings_enums.h index ccf6f1cfb2..0e5a08d845 100644 --- a/src/common/settings_enums.h +++ b/src/common/settings_enums.h @@ -142,8 +142,8 @@ ENUM(MemoryLayout, Memory_4Gb, Memory_6Gb, Memory_8Gb, Memory_10Gb, Memory_12Gb) ENUM(ConfirmStop, Ask_Always, Ask_Based_On_Game, Ask_Never); ENUM(FullscreenMode, Borderless, Exclusive); ENUM(NvdecEmulation, Off, Cpu, Gpu); -ENUM(ResolutionSetup, Res1_4X, Res1_2X, Res3_4X, Res1X, Res5_4X, Res3_2X, Res2X, Res3X, Res4X, Res5X, Res6X, Res7X, Res8X); -ENUM(ScalingFilter, NearestNeighbor, Bilinear, Bicubic, Gaussian, Lanczos, ScaleForce, Fsr, Area, ZeroTangent, BSpline, Mitchell, Spline1, Mmpx, MaxEnum); +ENUM(ResolutionSetup, Res1_4X, Res1_2X, Res3_4X, Res1X, Res3_2X, Res2X, Res3X, Res4X, Res5X, Res6X, Res7X, Res8X); +ENUM(ScalingFilter, NearestNeighbor, Bilinear, Bicubic, Spline1, Gaussian, Lanczos, ScaleForce, Fsr, Area, MaxEnum); ENUM(AntiAliasing, None, Fxaa, Smaa, MaxEnum); ENUM(AspectRatio, R16_9, R4_3, R21_9, R16_10, Stretch); ENUM(ConsoleMode, Handheld, Docked); diff --git a/src/common/thread.cpp b/src/common/thread.cpp index 2de7465a22..da1fa9b6c5 100644 --- a/src/common/thread.cpp +++ b/src/common/thread.cpp @@ -1,5 +1,6 @@ // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2013 Dolphin Emulator Project // SPDX-FileCopyrightText: 2014 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -17,8 +18,9 @@ #else #if defined(__Bitrig__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) #include -#endif +#else #include +#endif #include #endif #ifndef _WIN32 @@ -91,35 +93,33 @@ void SetCurrentThreadName(const char* name) { #else // !MSVC_VER, so must be POSIX threads // MinGW with the POSIX threading model does not support pthread_setname_np +#if !defined(_WIN32) || defined(_MSC_VER) void SetCurrentThreadName(const char* name) { - // See for reference - // https://gitlab.freedesktop.org/mesa/mesa/-/blame/main/src/util/u_thread.c?ref_type=heads#L75 #ifdef __APPLE__ pthread_setname_np(name); -#elif defined(__HAIKU__) - rename_thread(find_thread(NULL), name); #elif defined(__Bitrig__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) pthread_set_name_np(pthread_self(), name); #elif defined(__NetBSD__) pthread_setname_np(pthread_self(), "%s", (void*)name); -#elif defined(__linux__) || defined(__CYGWIN__) || defined(__sun__) || defined(__glibc__) || defined(__managarm__) - int ret = pthread_setname_np(pthread_self(), name); - if (ret == ERANGE) { - // Linux limits thread names to 15 characters and will outright reject any - // attempt to set a longer name with ERANGE. - char buf[16]; - size_t const len = std::min(std::strlen(name), sizeof(buf) - 1); - std::memcpy(buf, name, len); - buf[len] = '\0'; - pthread_setname_np(pthread_self(), buf); +#elif defined(__linux__) + // Linux limits thread names to 15 characters and will outright reject any + // attempt to set a longer name with ERANGE. + std::string truncated(name, (std::min)(strlen(name), static_cast(15))); + if (int e = pthread_setname_np(pthread_self(), truncated.c_str())) { + errno = e; + LOG_ERROR(Common, "Failed to set thread name to '{}': {}", truncated, GetLastErrorMsg()); } -#elif !defined(_WIN32) || defined(_MSC_VER) - // mingw stub - (void)name; #else pthread_setname_np(pthread_self(), name); #endif } +#endif + +#if defined(_WIN32) +void SetCurrentThreadName(const char* name) { + // Do Nothing on MingW +} +#endif #endif diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp index dda8d526d3..edf51e74de 100644 --- a/src/core/file_sys/savedata_factory.cpp +++ b/src/core/file_sys/savedata_factory.cpp @@ -4,6 +4,7 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include #include "common/assert.h" #include "common/common_types.h" #include "common/logging/log.h" @@ -128,6 +129,10 @@ std::string SaveDataFactory::GetFullPath(ProgramId program_id, VirtualDir dir, std::string out = GetSaveDataSpaceIdPath(space); + LOG_INFO(Common_Filesystem, "Save ID: {:016X}", save_id); + LOG_INFO(Common_Filesystem, "User ID[1]: {:016X}", user_id[1]); + LOG_INFO(Common_Filesystem, "User ID[0]: {:016X}", user_id[0]); + switch (type) { case SaveDataType::System: return fmt::format("{}save/{:016X}/{:016X}{:016X}", out, save_id, user_id[1], user_id[0]); diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp index 12ea5f7aa1..a4394046fa 100644 --- a/src/core/hle/service/acc/profile_manager.cpp +++ b/src/core/hle/service/acc/profile_manager.cpp @@ -4,17 +4,13 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include #include -#include -#include #include #include #include "common/fs/file.h" #include "common/fs/fs.h" -#include "common/fs/fs_types.h" #include "common/fs/path_util.h" #include #include "common/settings.h" @@ -94,11 +90,6 @@ bool ProfileManager::RemoveProfileAtIndex(std::size_t index) { return true; } -void ProfileManager::RemoveAllProfiles() -{ - profiles = {}; -} - /// Helper function to register a user to the system Result ProfileManager::AddUser(const ProfileInfo& user) { if (!AddToProfiles(user)) { @@ -268,9 +259,8 @@ void ProfileManager::CloseUser(UUID uuid) { /// Gets all valid user ids on the system UserIDArray ProfileManager::GetAllUsers() const { UserIDArray output{}; - std::ranges::transform(profiles, output.begin(), [](const ProfileInfo& p) { - return p.user_uuid; - }); + std::ranges::transform(profiles, output.begin(), + [](const ProfileInfo& p) { return p.user_uuid; }); return output; } @@ -397,19 +387,18 @@ bool ProfileManager::SetProfileBaseAndData(Common::UUID uuid, const ProfileBase& void ProfileManager::ParseUserSaveFile() { const auto save_path(FS::GetEdenPath(FS::EdenPath::NANDDir) / ACC_SAVE_AVATORS_BASE_PATH / "profiles.dat"); - const FS::IOFile save(save_path, FS::FileAccessMode::Read, FS::FileType::BinaryFile); if (!save.IsOpen()) { LOG_WARNING(Service_ACC, "Failed to load profile data from save data... Generating new " - "user 'Eden' with random UUID."); + "user 'eden' with random UUID."); return; } ProfileDataRaw data; if (!save.ReadObject(data)) { LOG_WARNING(Service_ACC, "profiles.dat is smaller than expected... Generating new user " - "'Eden' with random UUID."); + "'eden' with random UUID."); return; } @@ -482,82 +471,6 @@ void ProfileManager::WriteUserSaveFile() { is_save_needed = false; } -void ProfileManager::ResetUserSaveFile() -{ - RemoveAllProfiles(); - ParseUserSaveFile(); -} - -std::vector ProfileManager::FindOrphanedProfiles() -{ - std::vector good_uuids; - - for (const ProfileInfo& p : profiles) { - std::string uuid_string = [p]() -> std::string { - auto uuid = p.user_uuid; - - // "ignore" invalid uuids - if (uuid.IsInvalid()) { - return "0"; - } - - auto user_id = uuid.AsU128(); - - return fmt::format("{:016X}{:016X}", user_id[1], user_id[0]); - }(); - - good_uuids.emplace_back(uuid_string); - } - - // used for acnh, etc - good_uuids.emplace_back("00000000000000000000000000000000"); - - // TODO: fetch save_id programmatically - const auto path = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) - / "user/save/0000000000000000"; - - std::vector orphaned_profiles; - - Common::FS::IterateDirEntries( - path, - [&good_uuids, &orphaned_profiles](const std::filesystem::directory_entry& entry) -> bool { - const std::string uuid = entry.path().stem().string(); - - // first off, we should always clear empty profiles - // 99% of the time these are useless. If not, they are recreated anyways... - namespace fs = std::filesystem; - - const auto is_empty = [&entry]() -> bool { - try { - for (const auto& file : fs::recursive_directory_iterator(entry.path())) { - if (file.is_regular_file()) { - return true; - } - } - } catch (const fs::filesystem_error& e) { - // if we get an error--no worries, just pretend it's not empty - return false; - } - return false; - }(); - - if (!is_empty) { - fs::remove_all(entry); - return true; - } - - // if profiles.dat contains the UUID--all good - // if not--it's an orphaned profile and should be resolved by the user - if (std::find(good_uuids.begin(), good_uuids.end(), uuid) == good_uuids.end()) { - orphaned_profiles.emplace_back(uuid); - } - return true; - }, - Common::FS::DirEntryFilter::Directory); - - return orphaned_profiles; -} - void ProfileManager::SetUserPosition(u64 position, Common::UUID uuid) { auto idxOpt = GetUserIndex(uuid); if (!idxOpt) diff --git a/src/core/hle/service/acc/profile_manager.h b/src/core/hle/service/acc/profile_manager.h index b164ed011a..d64e42715c 100644 --- a/src/core/hle/service/acc/profile_manager.h +++ b/src/core/hle/service/acc/profile_manager.h @@ -103,15 +103,10 @@ public: void WriteUserSaveFile(); - void ResetUserSaveFile(); - - std::vector FindOrphanedProfiles(); - private: void ParseUserSaveFile(); std::optional AddToProfiles(const ProfileInfo& profile); bool RemoveProfileAtIndex(std::size_t index); - void RemoveAllProfiles(); bool is_save_needed{}; std::array profiles{}; diff --git a/src/core/hle/service/ns/query_service.cpp b/src/core/hle/service/ns/query_service.cpp index a4632cb6c8..1384005415 100644 --- a/src/core/hle/service/ns/query_service.cpp +++ b/src/core/hle/service/ns/query_service.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -32,7 +29,7 @@ IQueryService::IQueryService(Core::System& system_) : ServiceFramework{system_, {14, nullptr, "QueryRecentlyPlayedApplication"}, {15, nullptr, "GetRecentlyPlayedApplicationUpdateEvent"}, {16, nullptr, "QueryApplicationPlayStatisticsByUserAccountIdForSystemV0"}, - {17, D<&IQueryService::QueryLastPlayTime>, "QueryLastPlayTime"}, + {17, nullptr, "QueryLastPlayTime"}, {18, nullptr, "QueryApplicationPlayStatisticsForSystem"}, {19, nullptr, "QueryApplicationPlayStatisticsByUserAccountIdForSystem"}, }; @@ -56,13 +53,4 @@ Result IQueryService::QueryPlayStatisticsByApplicationIdAndUserAccountId( R_SUCCEED(); } -Result IQueryService::QueryLastPlayTime( - Out out_entries, u8 unknown, - OutArray out_last_play_times, - InArray application_ids) { - *out_entries = 1; - *out_last_play_times = {}; - R_SUCCEED(); -} - } // namespace Service::NS diff --git a/src/core/hle/service/ns/query_service.h b/src/core/hle/service/ns/query_service.h index ba1cddd4ca..c4c82b752e 100644 --- a/src/core/hle/service/ns/query_service.h +++ b/src/core/hle/service/ns/query_service.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -26,8 +23,6 @@ struct PlayStatistics { }; static_assert(sizeof(PlayStatistics) == 0x28, "PlayStatistics is an invalid size"); -struct LastPlayTime {}; - class IQueryService final : public ServiceFramework { public: explicit IQueryService(Core::System& system_); @@ -36,9 +31,6 @@ public: private: Result QueryPlayStatisticsByApplicationIdAndUserAccountId( Out out_play_statistics, bool unknown, u64 application_id, Uid account_id); - Result QueryLastPlayTime(Out out_entries, u8 unknown, - OutArray out_last_play_times, - InArray application_ids); }; } // namespace Service::NS diff --git a/src/dynarmic/CMakeLists.txt b/src/dynarmic/CMakeLists.txt index e5345ef458..6b3308fb54 100644 --- a/src/dynarmic/CMakeLists.txt +++ b/src/dynarmic/CMakeLists.txt @@ -25,7 +25,11 @@ option(DYNARMIC_IGNORE_ASSERTS "Ignore asserts" OFF) option(DYNARMIC_TESTS_USE_UNICORN "Enable fuzzing tests against unicorn" OFF) CMAKE_DEPENDENT_OPTION(DYNARMIC_USE_LLVM "Support disassembly of jitted x86_64 code using LLVM" OFF "NOT YUZU_DISABLE_LLVM" OFF) -option(DYNARMIC_USE_PRECOMPILED_HEADERS "Use precompiled headers" OFF) +if (PLATFORM_OPENBSD) + option(DYNARMIC_USE_PRECOMPILED_HEADERS "Use precompiled headers" OFF) +else() + option(DYNARMIC_USE_PRECOMPILED_HEADERS "Use precompiled headers" ON) +endif() option(DYNARMIC_INSTALL "Install dynarmic headers and CMake files" OFF) option(DYNARMIC_USE_BUNDLED_EXTERNALS "Use all bundled externals (useful when e.g. cross-compiling)" OFF) @@ -77,6 +81,7 @@ if (MSVC) /wd4592 # Symbol will be dynamically initialized (implementation limitation) /permissive- # Stricter C++ standards conformance /MP + /Zi /Zo /EHsc /Zc:externConstexpr # Allows external linkage for variables declared "extern constexpr", as the standard permits. @@ -86,11 +91,6 @@ if (MSVC) /bigobj # Increase number of sections in .obj files /DNOMINMAX) - if (WIN32 AND (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")) - string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") - string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") - endif() - if (DYNARMIC_WARNINGS_AS_ERRORS) list(APPEND DYNARMIC_CXX_FLAGS /WX) diff --git a/src/dynarmic/src/dynarmic/backend/arm64/abi.h b/src/dynarmic/src/dynarmic/backend/arm64/abi.h index 635d64f062..ca7c9187db 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/abi.h +++ b/src/dynarmic/src/dynarmic/backend/arm64/abi.h @@ -14,7 +14,6 @@ #include #include "dynarmic/common/common_types.h" -#include "dynarmic/common/assert.h" #include #include "dynarmic/common/always_false.h" diff --git a/src/dynarmic/src/dynarmic/common/assert.h b/src/dynarmic/src/dynarmic/common/assert.h index 0a3cb5331d..9973b8948d 100644 --- a/src/dynarmic/src/dynarmic/common/assert.h +++ b/src/dynarmic/src/dynarmic/common/assert.h @@ -23,12 +23,6 @@ template } \ }()) #endif -#ifndef ASSERT_FALSE -#define ASSERT_FALSE(...) \ - ([&]() { \ - assert_terminate("false", __VA_ARGS__); \ - }()) -#endif #ifndef ASSERT #define ASSERT(_a_) ASSERT_MSG(_a_, "") diff --git a/src/dynarmic/src/dynarmic/common/memory_pool.h b/src/dynarmic/src/dynarmic/common/memory_pool.h index d0a5223db3..c99316e107 100644 --- a/src/dynarmic/src/dynarmic/common/memory_pool.h +++ b/src/dynarmic/src/dynarmic/common/memory_pool.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - /* This file is part of the dynarmic project. * Copyright (c) 2016 MerryMage * SPDX-License-Identifier: 0BSD @@ -9,7 +6,6 @@ #pragma once #include -#include #include namespace Dynarmic::Common { diff --git a/src/dynarmic/src/dynarmic/ir/opt_passes.cpp b/src/dynarmic/src/dynarmic/ir/opt_passes.cpp index 25afde9b5d..e9175f0e6b 100644 --- a/src/dynarmic/src/dynarmic/ir/opt_passes.cpp +++ b/src/dynarmic/src/dynarmic/ir/opt_passes.cpp @@ -6,7 +6,6 @@ * SPDX-License-Identifier: 0BSD */ -#include #include #include diff --git a/src/qt_common/qt_content_util.cpp b/src/qt_common/qt_content_util.cpp index 2f659cf1b2..e4625aa423 100644 --- a/src/qt_common/qt_content_util.cpp +++ b/src/qt_common/qt_content_util.cpp @@ -1,10 +1,8 @@ // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later -#include "qt_common/qt_game_util.h" #include "qt_content_util.h" #include "common/fs/fs.h" -#include "core/hle/service/acc/profile_manager.h" #include "frontend_common/content_manager.h" #include "frontend_common/firmware_manager.h" #include "qt_common/qt_common.h" @@ -312,40 +310,4 @@ void VerifyInstalledContents() { } } -void FixProfiles() -{ - // Reset user save files after config is initialized and migration is done. - // Doing it at init time causes profiles to read from the wrong place entirely if NAND dir is not default - // TODO: better solution - system->GetProfileManager().ResetUserSaveFile(); - std::vector orphaned = system->GetProfileManager().FindOrphanedProfiles(); - - // no orphaned dirs--all good :) - if (orphaned.empty()) - return; - - // otherwise, let the user know - QString qorphaned; - - // max. of 8 orphaned profiles is fair, I think - // 33 = 32 (UUID) + 1 (\n) - qorphaned.reserve(8 * 33); - - for (const std::string& s : orphaned) { - qorphaned += "\n" + QString::fromStdString(s); - } - - QtCommon::Frontend::Critical( - tr("Orphaned Profiles Detected!"), - tr("UNEXPECTED BAD THINGS MAY HAPPEN IF YOU DON'T READ THIS!\n" - "Eden has detected the following save directories with no attached profile:\n" - "%1\n\n" - "Click \"OK\" to open your save folder and fix up your profiles.\n" - "Hint: copy the contents of the largest or last-modified folder elsewhere, " - "delete all orphaned profiles, and move your copied contents to the good profile.") - .arg(qorphaned)); - - QtCommon::Game::OpenSaveFolder(); -} - } // namespace QtCommon::Content diff --git a/src/qt_common/qt_content_util.h b/src/qt_common/qt_content_util.h index b95e78c0a0..b572c1c4a3 100644 --- a/src/qt_common/qt_content_util.h +++ b/src/qt_common/qt_content_util.h @@ -45,8 +45,5 @@ void InstallKeys(); // Content // void VerifyGameContents(const std::string &game_path); void VerifyInstalledContents(); - -// Profiles // -void FixProfiles(); } #endif // QT_CONTENT_UTIL_H diff --git a/src/qt_common/qt_game_util.cpp b/src/qt_common/qt_game_util.cpp index ac922ea967..5d0b4d8ae7 100644 --- a/src/qt_common/qt_game_util.cpp +++ b/src/qt_common/qt_game_util.cpp @@ -178,12 +178,6 @@ void OpenNANDFolder() OpenEdenFolder(Common::FS::EdenPath::NANDDir); } -void OpenSaveFolder() -{ - const auto path = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "user/save/0000000000000000"; - QDesktopServices::openUrl(QUrl::fromLocalFile(QString::fromStdString(path.string()))); -} - void OpenSDMCFolder() { OpenEdenFolder(Common::FS::EdenPath::SDMCDir); @@ -385,21 +379,21 @@ void RemoveCacheStorage(u64 program_id) } // Metadata // -void ResetMetadata(bool show_message) +void ResetMetadata() { const QString title = tr("Reset Metadata Cache"); if (!Common::FS::Exists(Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir) / "game_list/")) { - if (show_message) QtCommon::Frontend::Warning(rootObject, title, tr("The metadata cache is already empty.")); + QtCommon::Frontend::Warning(rootObject, title, tr("The metadata cache is already empty.")); } else if (Common::FS::RemoveDirRecursively( Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir) / "game_list")) { - if (show_message) QtCommon::Frontend::Information(rootObject, + QtCommon::Frontend::Information(rootObject, title, tr("The operation completed successfully.")); UISettings::values.is_game_list_reload_pending.exchange(true); } else { - if (show_message) QtCommon::Frontend::Warning( + QtCommon::Frontend::Warning( rootObject, title, tr("The metadata cache couldn't be deleted. It might be in use or non-existent.")); @@ -579,4 +573,5 @@ void CreateHomeMenuShortcut(ShortcutTarget target) { CreateShortcut(game_path, QLaunchId, "Switch Home Menu", target, "-qlaunch", false); } + } // namespace QtCommon::Game diff --git a/src/qt_common/qt_game_util.h b/src/qt_common/qt_game_util.h index 5c6bb24910..0a21208659 100644 --- a/src/qt_common/qt_game_util.h +++ b/src/qt_common/qt_game_util.h @@ -52,7 +52,6 @@ bool MakeShortcutIcoPath(const u64 program_id, void OpenEdenFolder(const Common::FS::EdenPath &path); void OpenRootDataFolder(); void OpenNANDFolder(); -void OpenSaveFolder(); void OpenSDMCFolder(); void OpenModFolder(); void OpenLogFolder(); @@ -68,7 +67,7 @@ void RemoveCustomConfiguration(u64 program_id, const std::string& game_path); void RemoveCacheStorage(u64 program_id); // Metadata // -void ResetMetadata(bool show_message = true); +void ResetMetadata(); // Shortcuts // void CreateShortcut(const std::string& game_path, diff --git a/src/qt_common/shared_translation.cpp b/src/qt_common/shared_translation.cpp index 054d28e8e2..8f5d929b74 100644 --- a/src/qt_common/shared_translation.cpp +++ b/src/qt_common/shared_translation.cpp @@ -320,6 +320,12 @@ std::unique_ptr InitializeTranslations(QObject* parent) tr("Improves rendering of transparency effects in specific games.")); // Renderer (Extensions) + INSERT(Settings, + enable_raii, + tr("RAII"), + tr("A method of automatic resource management in Vulkan " + "that ensures proper release of resources " + "when they are no longer needed, but may cause crashes in bundled games.")); INSERT(Settings, dyna_state, tr("Extended Dynamic State"), @@ -534,7 +540,6 @@ std::unique_ptr ComboboxEnumeration(QObject* parent) PAIR(ResolutionSetup, Res1_2X, tr("0.5X (360p/540p) [EXPERIMENTAL]")), PAIR(ResolutionSetup, Res3_4X, tr("0.75X (540p/810p) [EXPERIMENTAL]")), PAIR(ResolutionSetup, Res1X, tr("1X (720p/1080p)")), - PAIR(ResolutionSetup, Res5_4X, tr("1.25X (900p/1350p) [EXPERIMENTAL]")), PAIR(ResolutionSetup, Res3_2X, tr("1.5X (1080p/1620p) [EXPERIMENTAL]")), PAIR(ResolutionSetup, Res2X, tr("2X (1440p/2160p)")), PAIR(ResolutionSetup, Res3X, tr("3X (2160p/3240p)")), @@ -549,16 +554,12 @@ std::unique_ptr ComboboxEnumeration(QObject* parent) PAIR(ScalingFilter, NearestNeighbor, tr("Nearest Neighbor")), PAIR(ScalingFilter, Bilinear, tr("Bilinear")), PAIR(ScalingFilter, Bicubic, tr("Bicubic")), + PAIR(ScalingFilter, Spline1, tr("Spline-1")), PAIR(ScalingFilter, Gaussian, tr("Gaussian")), PAIR(ScalingFilter, Lanczos, tr("Lanczos")), PAIR(ScalingFilter, ScaleForce, tr("ScaleForce")), PAIR(ScalingFilter, Fsr, tr("AMD FidelityFX™️ Super Resolution")), PAIR(ScalingFilter, Area, tr("Area")), - PAIR(ScalingFilter, Mmpx, tr("MMPX")), - PAIR(ScalingFilter, ZeroTangent, tr("Zero-Tangent")), - PAIR(ScalingFilter, BSpline, tr("B-Spline")), - PAIR(ScalingFilter, Mitchell, tr("Mitchell")), - PAIR(ScalingFilter, Spline1, tr("Spline-1")), }}); translations->insert({Settings::EnumMetadata::Index(), { @@ -715,4 +716,3 @@ std::unique_ptr ComboboxEnumeration(QObject* parent) return translations; } } // namespace ConfigurationShared - diff --git a/src/qt_common/shared_translation.h b/src/qt_common/shared_translation.h index a25887bb87..c9216c2daa 100644 --- a/src/qt_common/shared_translation.h +++ b/src/qt_common/shared_translation.h @@ -38,9 +38,6 @@ static const std::map scaling_filter_texts_map {Settings::ScalingFilter::Bilinear, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Bilinear"))}, {Settings::ScalingFilter::Bicubic, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Bicubic"))}, - {Settings::ScalingFilter::ZeroTangent, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Zero-Tangent"))}, - {Settings::ScalingFilter::BSpline, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "B-Spline"))}, - {Settings::ScalingFilter::Mitchell, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Mitchell"))}, {Settings::ScalingFilter::Spline1, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Spline-1"))}, {Settings::ScalingFilter::Gaussian, @@ -51,7 +48,6 @@ static const std::map scaling_filter_texts_map QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "ScaleForce"))}, {Settings::ScalingFilter::Fsr, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FSR"))}, {Settings::ScalingFilter::Area, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Area"))}, - {Settings::ScalingFilter::Mmpx, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "MMPX"))}, }; static const std::map use_docked_mode_texts_map = { diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index 9f7b9edd5a..c14b44a45a 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt @@ -44,13 +44,9 @@ set(SHADER_FILES pitch_unswizzle.comp present_area.frag present_bicubic.frag - present_zero_tangent.frag - present_bspline.frag - present_mitchell.frag present_gaussian.frag present_lanczos.frag present_spline1.frag - present_mmpx.frag queries_prefix_scan_sum.comp queries_prefix_scan_sum_nosubgroups.comp resolve_conditional_render.comp diff --git a/src/video_core/host_shaders/present_bicubic.frag b/src/video_core/host_shaders/present_bicubic.frag index 5347fd2ef7..a9d9d40a38 100644 --- a/src/video_core/host_shaders/present_bicubic.frag +++ b/src/video_core/host_shaders/present_bicubic.frag @@ -1,37 +1,56 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later + #version 460 core + + layout (location = 0) in vec2 frag_tex_coord; + layout (location = 0) out vec4 color; + layout (binding = 0) uniform sampler2D color_texture; -vec4 cubic(float x) { - float x2 = x * x; - float x3 = x2 * x; - return vec4(1.0, x, x2, x3) * transpose(mat4x4( - 0.0, 2.0, 0.0, 0.0, - -1.0, 0.0, 1.0, 0.0, - 2.0, -5.0, 4.0, -1.0, - -1.0, 3.0, -3.0, 1.0 - ) * (1.0 / 2.0)); + +vec4 cubic(float v) { + vec4 n = vec4(1.0, 2.0, 3.0, 4.0) - v; + vec4 s = n * n * n; + float x = s.x; + float y = s.y - 4.0 * s.x; + float z = s.z - 4.0 * s.y + 6.0 * s.x; + float w = 6.0 - x - y - z; + return vec4(x, y, z, w) * (1.0 / 6.0); } -vec4 textureBicubic(sampler2D samp, vec2 uv) { - vec2 tex_size = vec2(textureSize(samp, 0)); - vec2 cc_tex = uv * tex_size - 0.5f; - vec2 fex = cc_tex - floor(cc_tex); - vec4 xcubic = cubic(fex.x); - vec4 ycubic = cubic(fex.y); - vec4 c = floor(cc_tex).xxyy + vec2(-0.5f, 1.5f).xyxy; - vec4 z = vec4(xcubic.yw, ycubic.yw); - vec4 s = vec4(xcubic.xz, ycubic.xz) + z; - vec4 offset = (c + z / s) * (1.0f / tex_size).xxyy; - vec2 n = vec2(s.x / (s.x + s.y), s.z / (s.z + s.w)); - return mix( - mix(texture(samp, offset.yw), texture(samp, offset.xw), n.x), - mix(texture(samp, offset.yz), texture(samp, offset.xz), n.x), - n.y); + +vec4 textureBicubic( sampler2D textureSampler, vec2 texCoords ) { + + vec2 texSize = textureSize(textureSampler, 0); + vec2 invTexSize = 1.0 / texSize; + + texCoords = texCoords * texSize - 0.5; + + vec2 fxy = fract(texCoords); + texCoords -= fxy; + + vec4 xcubic = cubic(fxy.x); + vec4 ycubic = cubic(fxy.y); + + vec4 c = texCoords.xxyy + vec2(-0.5, +1.5).xyxy; + + vec4 s = vec4(xcubic.xz + xcubic.yw, ycubic.xz + ycubic.yw); + vec4 offset = c + vec4(xcubic.yw, ycubic.yw) / s; + + offset *= invTexSize.xxyy; + + vec4 sample0 = texture(textureSampler, offset.xz); + vec4 sample1 = texture(textureSampler, offset.yz); + vec4 sample2 = texture(textureSampler, offset.xw); + vec4 sample3 = texture(textureSampler, offset.yw); + + float sx = s.x / (s.x + s.y); + float sy = s.z / (s.z + s.w); + + return mix(mix(sample3, sample2, sx), mix(sample1, sample0, sx), sy); } + void main() { color = textureBicubic(color_texture, frag_tex_coord); } diff --git a/src/video_core/host_shaders/present_bspline.frag b/src/video_core/host_shaders/present_bspline.frag deleted file mode 100644 index f229de6030..0000000000 --- a/src/video_core/host_shaders/present_bspline.frag +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later -#version 460 core -layout (location = 0) in vec2 frag_tex_coord; -layout (location = 0) out vec4 color; -layout (binding = 0) uniform sampler2D color_texture; -vec4 cubic(float x) { - float x2 = x * x; - float x3 = x2 * x; - return vec4(1.0, x, x2, x3) * transpose(mat4x4( - 1.0, 4.0, 1.0, 0.0, - -3.0, 0.0, 3.0, 0.0, - 3.0, -6.0, 3.0, 0.0, - -1.0, 3.0, -3.0, 1.0 - ) * (1.0 / 6.0)); -} -vec4 textureBicubic(sampler2D samp, vec2 uv) { - vec2 tex_size = vec2(textureSize(samp, 0)); - vec2 cc_tex = uv * tex_size - 0.5f; - vec2 fex = cc_tex - floor(cc_tex); - vec4 xcubic = cubic(fex.x); - vec4 ycubic = cubic(fex.y); - vec4 c = floor(cc_tex).xxyy + vec2(-0.5f, 1.5f).xyxy; - vec4 z = vec4(xcubic.yw, ycubic.yw); - vec4 s = vec4(xcubic.xz, ycubic.xz) + z; - vec4 offset = (c + z / s) * (1.0f / tex_size).xxyy; - vec2 n = vec2(s.x / (s.x + s.y), s.z / (s.z + s.w)); - return mix( - mix(texture(samp, offset.yw), texture(samp, offset.xw), n.x), - mix(texture(samp, offset.yz), texture(samp, offset.xz), n.x), - n.y); -} -void main() { - color = textureBicubic(color_texture, frag_tex_coord); -} diff --git a/src/video_core/host_shaders/present_mitchell.frag b/src/video_core/host_shaders/present_mitchell.frag deleted file mode 100644 index 4ca65cd6f0..0000000000 --- a/src/video_core/host_shaders/present_mitchell.frag +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later -#version 460 core -layout (location = 0) in vec2 frag_tex_coord; -layout (location = 0) out vec4 color; -layout (binding = 0) uniform sampler2D color_texture; -vec4 cubic(float x) { - float x2 = x * x; - float x3 = x2 * x; - return vec4(1.0, x, x2, x3) * transpose(mat4x4( - 1.0, 16.0, 1.0, 0.0, - -9.0, 0.0, 9.0, 0.0, - 15.0, -36.0, 27.0, -6.0, - -7.0, 21.0, -21.0, 7.0 - ) * (1.0 / 18.0)); -} -vec4 textureBicubic(sampler2D samp, vec2 uv) { - vec2 tex_size = vec2(textureSize(samp, 0)); - vec2 cc_tex = uv * tex_size - 0.5f; - vec2 fex = cc_tex - floor(cc_tex); - vec4 xcubic = cubic(fex.x); - vec4 ycubic = cubic(fex.y); - vec4 c = floor(cc_tex).xxyy + vec2(-0.5f, 1.5f).xyxy; - vec4 z = vec4(xcubic.yw, ycubic.yw); - vec4 s = vec4(xcubic.xz, ycubic.xz) + z; - vec4 offset = (c + z / s) * (1.0f / tex_size).xxyy; - vec2 n = vec2(s.x / (s.x + s.y), s.z / (s.z + s.w)); - return mix( - mix(texture(samp, offset.yw), texture(samp, offset.xw), n.x), - mix(texture(samp, offset.yz), texture(samp, offset.xz), n.x), - n.y); -} -void main() { - color = textureBicubic(color_texture, frag_tex_coord); -} diff --git a/src/video_core/host_shaders/present_mmpx.frag b/src/video_core/host_shaders/present_mmpx.frag deleted file mode 100644 index 6c2c05a63a..0000000000 --- a/src/video_core/host_shaders/present_mmpx.frag +++ /dev/null @@ -1,131 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later -// Copyright 2023 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#version 460 core -layout(location = 0) in vec2 tex_coord; -layout(location = 0) out vec4 frag_color; -layout(binding = 0) uniform sampler2D tex; - -#define src(x, y) texture(tex, coord + vec2(x, y) * 1.0 / source_size) - -float luma(vec4 col) { - return dot(col.rgb, vec3(0.2126, 0.7152, 0.0722)) * (1.0 - col.a); -} - -bool same(vec4 B, vec4 A0) { - return all(equal(B, A0)); -} - -bool notsame(vec4 B, vec4 A0) { - return any(notEqual(B, A0)); -} - -bool all_eq2(vec4 B, vec4 A0, vec4 A1) { - return (same(B,A0) && same(B,A1)); -} - -bool all_eq3(vec4 B, vec4 A0, vec4 A1, vec4 A2) { - return (same(B,A0) && same(B,A1) && same(B,A2)); -} - -bool all_eq4(vec4 B, vec4 A0, vec4 A1, vec4 A2, vec4 A3) { - return (same(B,A0) && same(B,A1) && same(B,A2) && same(B,A3)); -} - -bool any_eq3(vec4 B, vec4 A0, vec4 A1, vec4 A2) { - return (same(B,A0) || same(B,A1) || same(B,A2)); -} - -bool none_eq2(vec4 B, vec4 A0, vec4 A1) { - return (notsame(B,A0) && notsame(B,A1)); -} - -bool none_eq4(vec4 B, vec4 A0, vec4 A1, vec4 A2, vec4 A3) { - return (notsame(B,A0) && notsame(B,A1) && notsame(B,A2) && notsame(B,A3)); -} - -void main() -{ - vec2 source_size = vec2(textureSize(tex, 0)); - vec2 pos = fract(tex_coord * source_size) - vec2(0.5, 0.5); - vec2 coord = tex_coord - pos / source_size; - - vec4 E = src(0.0,0.0); - - vec4 A = src(-1.0,-1.0); - vec4 B = src(0.0,-1.0); - vec4 C = src(1.0,-1.0); - - vec4 D = src(-1.0,0.0); - vec4 F = src(1.0,0.0); - - vec4 G = src(-1.0,1.0); - vec4 H = src(0.0,1.0); - vec4 I = src(1.0,1.0); - - vec4 J = E; - vec4 K = E; - vec4 L = E; - vec4 M = E; - - frag_color = E; - - if(same(E,A) && same(E,B) && same(E,C) && same(E,D) && same(E,F) && same(E,G) && same(E,H) && same(E,I)) return; - - vec4 P = src(0.0,2.0); - vec4 Q = src(-2.0,0.0); - vec4 R = src(2.0,0.0); - vec4 S = src(0.0,2.0); - - float Bl = luma(B); - float Dl = luma(D); - float El = luma(E); - float Fl = luma(F); - float Hl = luma(H); - - if (((same(D,B) && notsame(D,H) && notsame(D,F))) && ((El>=Dl) || same(E,A)) && any_eq3(E,A,C,G) && ((El=Bl) || same(E,C)) && any_eq3(E,A,C,I) && ((El=Hl) || same(E,G)) && any_eq3(E,A,G,I) && ((El=Fl) || same(E,I)) && any_eq3(E,C,G,I) && ((El MakeBicubic(const Device& device) { HostShaders::PRESENT_BICUBIC_FRAG); } -std::unique_ptr MakeMitchell(const Device& device) { - return std::make_unique(device, CreateBilinearSampler(), - HostShaders::PRESENT_MITCHELL_FRAG); -} - -std::unique_ptr MakeZeroTangent(const Device& device) { - return std::make_unique(device, CreateBilinearSampler(), - HostShaders::PRESENT_ZERO_TANGENT_FRAG); -} - -std::unique_ptr MakeBSpline(const Device& device) { - return std::make_unique(device, CreateBilinearSampler(), - HostShaders::PRESENT_BSPLINE_FRAG); -} - std::unique_ptr MakeGaussian(const Device& device) { return std::make_unique(device, CreateBilinearSampler(), HostShaders::PRESENT_GAUSSIAN_FRAG); @@ -79,9 +60,4 @@ std::unique_ptr MakeArea(const Device& device) { HostShaders::PRESENT_AREA_FRAG); } -std::unique_ptr MakeMmpx(const Device& device) { - return std::make_unique(device, CreateNearestNeighborSampler(), - HostShaders::PRESENT_MMPX_FRAG); -} - } // namespace OpenGL diff --git a/src/video_core/renderer_opengl/present/filters.h b/src/video_core/renderer_opengl/present/filters.h index 187d0f1298..7b38ac56bc 100644 --- a/src/video_core/renderer_opengl/present/filters.h +++ b/src/video_core/renderer_opengl/present/filters.h @@ -17,14 +17,10 @@ namespace OpenGL { std::unique_ptr MakeNearestNeighbor(const Device& device); std::unique_ptr MakeBilinear(const Device& device); std::unique_ptr MakeBicubic(const Device& device); -std::unique_ptr MakeZeroTangent(const Device& device); -std::unique_ptr MakeMitchell(const Device& device); -std::unique_ptr MakeBSpline(const Device& device); std::unique_ptr MakeGaussian(const Device& device); std::unique_ptr MakeSpline1(const Device& device); std::unique_ptr MakeLanczos(const Device& device); std::unique_ptr MakeScaleForce(const Device& device); std::unique_ptr MakeArea(const Device& device); -std::unique_ptr MakeMmpx(const Device& device); } // namespace OpenGL diff --git a/src/video_core/renderer_vulkan/present/filters.cpp b/src/video_core/renderer_vulkan/present/filters.cpp index 0a28ea6349..e0f2b26f84 100644 --- a/src/video_core/renderer_vulkan/present/filters.cpp +++ b/src/video_core/renderer_vulkan/present/filters.cpp @@ -7,8 +7,6 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include -#include "common/assert.h" #include "common/common_types.h" #include "video_core/host_shaders/present_area_frag_spv.h" @@ -16,10 +14,6 @@ #include "video_core/host_shaders/present_gaussian_frag_spv.h" #include "video_core/host_shaders/present_lanczos_frag_spv.h" #include "video_core/host_shaders/present_spline1_frag_spv.h" -#include "video_core/host_shaders/present_mitchell_frag_spv.h" -#include "video_core/host_shaders/present_bspline_frag_spv.h" -#include "video_core/host_shaders/present_zero_tangent_frag_spv.h" -#include "video_core/host_shaders/present_mmpx_frag_spv.h" #include "video_core/host_shaders/vulkan_present_frag_spv.h" #include "video_core/host_shaders/vulkan_present_scaleforce_fp16_frag_spv.h" #include "video_core/host_shaders/vulkan_present_scaleforce_fp32_frag_spv.h" @@ -58,28 +52,13 @@ std::unique_ptr MakeSpline1(const Device& device, VkFormat fram BuildShader(device, PRESENT_SPLINE1_FRAG_SPV)); } -std::unique_ptr MakeBicubic(const Device& device, VkFormat frame_format, VkCubicFilterWeightsQCOM qcom_weights) { +std::unique_ptr MakeBicubic(const Device& device, VkFormat frame_format) { // No need for handrolled shader -- if the VK impl can do it for us ;) - // Catmull-Rom is default bicubic for all implementations... - if (device.IsExtFilterCubicSupported() && (device.IsQcomFilterCubicWeightsSupported() || qcom_weights == VK_CUBIC_FILTER_WEIGHTS_CATMULL_ROM_QCOM)) { - return std::make_unique(device, frame_format, CreateCubicSampler(device, - qcom_weights), BuildShader(device, VULKAN_PRESENT_FRAG_SPV)); - } else { - return std::make_unique(device, frame_format, CreateBilinearSampler(device), [&](){ - switch (qcom_weights) { - case VK_CUBIC_FILTER_WEIGHTS_CATMULL_ROM_QCOM: - return BuildShader(device, PRESENT_BICUBIC_FRAG_SPV); - case VK_CUBIC_FILTER_WEIGHTS_ZERO_TANGENT_CARDINAL_QCOM: - return BuildShader(device, PRESENT_ZERO_TANGENT_FRAG_SPV); - case VK_CUBIC_FILTER_WEIGHTS_B_SPLINE_QCOM: - return BuildShader(device, PRESENT_BSPLINE_FRAG_SPV); - case VK_CUBIC_FILTER_WEIGHTS_MITCHELL_NETRAVALI_QCOM: - return BuildShader(device, PRESENT_MITCHELL_FRAG_SPV); - default: - UNREACHABLE(); - } - }()); - } + if (device.IsExtFilterCubicSupported()) + return std::make_unique(device, frame_format, CreateCubicSampler(device), + BuildShader(device, VULKAN_PRESENT_FRAG_SPV)); + return std::make_unique(device, frame_format, CreateBilinearSampler(device), + BuildShader(device, PRESENT_BICUBIC_FRAG_SPV)); } std::unique_ptr MakeGaussian(const Device& device, VkFormat frame_format) { @@ -102,9 +81,4 @@ std::unique_ptr MakeArea(const Device& device, VkFormat frame_f BuildShader(device, PRESENT_AREA_FRAG_SPV)); } -std::unique_ptr MakeMmpx(const Device& device, VkFormat frame_format) { - return std::make_unique(device, frame_format, CreateNearestNeighborSampler(device), - BuildShader(device, PRESENT_MMPX_FRAG_SPV)); -} - } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/present/filters.h b/src/video_core/renderer_vulkan/present/filters.h index afc3ba29a0..015bffc8a5 100644 --- a/src/video_core/renderer_vulkan/present/filters.h +++ b/src/video_core/renderer_vulkan/present/filters.h @@ -17,12 +17,11 @@ class MemoryAllocator; std::unique_ptr MakeNearestNeighbor(const Device& device, VkFormat frame_format); std::unique_ptr MakeBilinear(const Device& device, VkFormat frame_format); -std::unique_ptr MakeBicubic(const Device& device, VkFormat frame_format, VkCubicFilterWeightsQCOM qcom_weights); +std::unique_ptr MakeBicubic(const Device& device, VkFormat frame_format); std::unique_ptr MakeSpline1(const Device& device, VkFormat frame_format); std::unique_ptr MakeGaussian(const Device& device, VkFormat frame_format); std::unique_ptr MakeLanczos(const Device& device, VkFormat frame_format); std::unique_ptr MakeScaleForce(const Device& device, VkFormat frame_format); std::unique_ptr MakeArea(const Device& device, VkFormat frame_format); -std::unique_ptr MakeMmpx(const Device& device, VkFormat frame_format); } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/present/layer.cpp b/src/video_core/renderer_vulkan/present/layer.cpp index fee19a69c2..5676dfe62a 100644 --- a/src/video_core/renderer_vulkan/present/layer.cpp +++ b/src/video_core/renderer_vulkan/present/layer.cpp @@ -332,7 +332,7 @@ void Layer::UpdateRawImage(const Tegra::FramebufferConfig& framebuffer, size_t i write_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; write_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, + cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, read_barrier); cmdbuf.CopyBufferToImage(*buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, copy); cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, diff --git a/src/video_core/renderer_vulkan/present/util.cpp b/src/video_core/renderer_vulkan/present/util.cpp index 29a1c34976..0b1a89eec0 100644 --- a/src/video_core/renderer_vulkan/present/util.cpp +++ b/src/video_core/renderer_vulkan/present/util.cpp @@ -624,8 +624,8 @@ vk::Sampler CreateNearestNeighborSampler(const Device& device) { return device.GetLogical().CreateSampler(ci_nn); } -vk::Sampler CreateCubicSampler(const Device& device, VkCubicFilterWeightsQCOM qcom_weights) { - VkSamplerCreateInfo ci_nn{ +vk::Sampler CreateCubicSampler(const Device& device) { + const VkSamplerCreateInfo ci_nn{ .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, .pNext = nullptr, .flags = 0, @@ -645,14 +645,7 @@ vk::Sampler CreateCubicSampler(const Device& device, VkCubicFilterWeightsQCOM qc .borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK, .unnormalizedCoordinates = VK_FALSE, }; - const VkSamplerCubicWeightsCreateInfoQCOM ci_qcom_nn{ - .sType = VK_STRUCTURE_TYPE_SAMPLER_CUBIC_WEIGHTS_CREATE_INFO_QCOM, - .pNext = nullptr, - .cubicWeights = qcom_weights - }; - // If not specified, assume Catmull-Rom - if (qcom_weights != VK_CUBIC_FILTER_WEIGHTS_CATMULL_ROM_QCOM) - ci_nn.pNext = &ci_qcom_nn; + return device.GetLogical().CreateSampler(ci_nn); } diff --git a/src/video_core/renderer_vulkan/present/util.h b/src/video_core/renderer_vulkan/present/util.h index 38cc6203c5..11810352df 100644 --- a/src/video_core/renderer_vulkan/present/util.h +++ b/src/video_core/renderer_vulkan/present/util.h @@ -57,7 +57,7 @@ VkWriteDescriptorSet CreateWriteDescriptorSet(std::vector VkDescriptorSet set, u32 binding); vk::Sampler CreateBilinearSampler(const Device& device); vk::Sampler CreateNearestNeighborSampler(const Device& device); -vk::Sampler CreateCubicSampler(const Device& device, VkCubicFilterWeightsQCOM qcom_weights); +vk::Sampler CreateCubicSampler(const Device& device); void BeginRenderPass(vk::CommandBuffer& cmdbuf, VkRenderPass render_pass, VkFramebuffer framebuffer, VkExtent2D extent); diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index e6e72cdca7..6f3a0e4cd1 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -164,6 +164,15 @@ try PresentFiltersForAppletCapture) , rasterizer(render_window, gpu, device_memory, device, memory_allocator, state_tracker, scheduler) { + // Initialize RAII wrappers after creating the main objects + if (Settings::values.enable_raii.GetValue()) { + managed_instance = MakeManagedInstance(instance, dld); + if (Settings::values.renderer_debug) { + managed_debug_messenger = MakeManagedDebugUtilsMessenger(debug_messenger, instance, dld); + } + managed_surface = MakeManagedSurface(surface, instance, dld); + } + if (Settings::values.renderer_force_max_clock.GetValue() && device.ShouldBoostClocks()) { turbo_mode.emplace(instance, dld); scheduler.RegisterOnSubmit([this] { turbo_mode->QueueSubmitted(); }); diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h index 4fb88b29de..c1e6d5db7f 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.h +++ b/src/video_core/renderer_vulkan/renderer_vulkan.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -23,6 +20,7 @@ #include "video_core/vulkan_common/vulkan_device.h" #include "video_core/vulkan_common/vulkan_memory_allocator.h" #include "video_core/vulkan_common/vulkan_wrapper.h" +#include "video_core/vulkan_common/vulkan_raii.h" namespace Core::Memory { class Memory; @@ -80,10 +78,16 @@ private: // Keep original handles for compatibility with existing code vk::Instance instance; + // RAII wrapper for instance + ManagedInstance managed_instance; vk::DebugUtilsMessenger debug_messenger; + // RAII wrapper for debug messenger + ManagedDebugUtilsMessenger managed_debug_messenger; vk::SurfaceKHR surface; + // RAII wrapper for surface + ManagedSurface managed_surface; Device device; MemoryAllocator memory_allocator; diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index 0f54dd5ade..b720bcded3 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp +++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp @@ -7,7 +7,6 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include #include "video_core/framebuffer_config.h" #include "video_core/present.h" #include "video_core/renderer_vulkan/present/filters.h" @@ -42,16 +41,7 @@ void BlitScreen::SetWindowAdaptPass() { window_adapt = MakeNearestNeighbor(device, swapchain_view_format); break; case Settings::ScalingFilter::Bicubic: - window_adapt = MakeBicubic(device, swapchain_view_format, VK_CUBIC_FILTER_WEIGHTS_CATMULL_ROM_QCOM); - break; - case Settings::ScalingFilter::ZeroTangent: - window_adapt = MakeBicubic(device, swapchain_view_format, VK_CUBIC_FILTER_WEIGHTS_ZERO_TANGENT_CARDINAL_QCOM); - break; - case Settings::ScalingFilter::BSpline: - window_adapt = MakeBicubic(device, swapchain_view_format, VK_CUBIC_FILTER_WEIGHTS_B_SPLINE_QCOM); - break; - case Settings::ScalingFilter::Mitchell: - window_adapt = MakeBicubic(device, swapchain_view_format, VK_CUBIC_FILTER_WEIGHTS_MITCHELL_NETRAVALI_QCOM); + window_adapt = MakeBicubic(device, swapchain_view_format); break; case Settings::ScalingFilter::Spline1: window_adapt = MakeSpline1(device, swapchain_view_format); @@ -68,9 +58,6 @@ void BlitScreen::SetWindowAdaptPass() { case Settings::ScalingFilter::Area: window_adapt = MakeArea(device, swapchain_view_format); break; - case Settings::ScalingFilter::Mmpx: - window_adapt = MakeMmpx(device, swapchain_view_format); - break; case Settings::ScalingFilter::Fsr: case Settings::ScalingFilter::Bilinear: default: diff --git a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp index 3af9758a31..e6b9662c85 100644 --- a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp +++ b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp @@ -96,9 +96,30 @@ VkDescriptorSet DescriptorAllocator::Commit() { const size_t index = CommitResource(); return sets[index / SETS_GROW_RATE][index % SETS_GROW_RATE]; } - +VkDescriptorSet DescriptorAllocator::CommitWithTracking(u64 current_frame, const void* descriptor_data) { + const size_t index = CommitResource(); + const size_t group = index / SETS_GROW_RATE; + const size_t slot = index % SETS_GROW_RATE; + set_states[group][slot].set = sets[group][slot]; + set_states[group][slot].last_update_frame = current_frame; + set_states[group][slot].last_data_ptr = descriptor_data; + return set_states[group][slot].set; + } +bool DescriptorAllocator::NeedsUpdate(VkDescriptorSet set, u64 current_frame, const void* descriptor_data) const { + for (const auto& group : set_states) { + for (const auto& st : group) { + if (st.set == set) { + // Update if pointer changed or the set hasn't been updated this frame + return st.last_data_ptr != descriptor_data || st.last_update_frame != current_frame; + } + } + } + return true; + } void DescriptorAllocator::Allocate(size_t begin, size_t end) { - sets.push_back(AllocateDescriptors(end - begin)); + const size_t count = end - begin; + sets.push_back(AllocateDescriptors(count)); + set_states.emplace_back(count); // create parallel state storage } vk::DescriptorSets DescriptorAllocator::AllocateDescriptors(size_t count) { diff --git a/src/video_core/renderer_vulkan/vk_descriptor_pool.h b/src/video_core/renderer_vulkan/vk_descriptor_pool.h index 4aada5a006..0a8d1afaa9 100644 --- a/src/video_core/renderer_vulkan/vk_descriptor_pool.h +++ b/src/video_core/renderer_vulkan/vk_descriptor_pool.h @@ -6,7 +6,7 @@ #include #include #include - +#include "common/common_types.h" #include "shader_recompiler/shader_info.h" #include "video_core/renderer_vulkan/vk_resource_pool.h" #include "video_core/vulkan_common/vulkan_wrapper.h" @@ -44,7 +44,15 @@ public: DescriptorAllocator(const DescriptorAllocator&) = delete; VkDescriptorSet Commit(); + // commit + remember when/with what we last updated this set + struct DescriptorSetState { + VkDescriptorSet set = VK_NULL_HANDLE; + u64 last_update_frame = 0; + const void* last_data_ptr = nullptr; // fast pointer compare + }; + VkDescriptorSet CommitWithTracking(u64 current_frame, const void* descriptor_data); + bool NeedsUpdate(VkDescriptorSet set, u64 current_frame, const void* descriptor_data) const; private: explicit DescriptorAllocator(const Device& device_, MasterSemaphore& master_semaphore_, DescriptorBank& bank_, VkDescriptorSetLayout layout_); @@ -58,6 +66,7 @@ private: VkDescriptorSetLayout layout{}; std::vector sets; + std::vector> set_states; }; class DescriptorPool { diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 745389213e..c18571c54e 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -513,7 +513,25 @@ void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling, const bool update_rescaling{scheduler.UpdateRescaling(is_rescaling)}; const bool bind_pipeline{scheduler.UpdateGraphicsPipeline(this)}; const void* const descriptor_data{guest_descriptor_queue.UpdateData()}; - scheduler.Record([this, descriptor_data, bind_pipeline, rescaling_data = rescaling.Data(), + + // allocate/bind descriptor set and only update if needed + VkDescriptorSet descriptor_set = VK_NULL_HANDLE; + bool needs_update = false; + if (descriptor_set_layout) { + if (uses_push_descriptor) { + // handled below via push descriptor + } else { + descriptor_set = descriptor_allocator.CommitWithTracking(current_frame_number, descriptor_data); + needs_update = descriptor_allocator.NeedsUpdate(descriptor_set, current_frame_number, descriptor_data); + if (needs_update) { + const vk::Device& dev{device.GetLogical()}; + dev.UpdateDescriptorSet(descriptor_set, *descriptor_update_template, descriptor_data); + } else { + } + } + } + + scheduler.Record([this, descriptor_data, descriptor_set, bind_pipeline, rescaling_data = rescaling.Data(), is_rescaling, update_rescaling, uses_render_area = render_area.uses_render_area, render_area_data = render_area.words](vk::CommandBuffer cmdbuf) { @@ -539,12 +557,8 @@ void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling, return; } if (uses_push_descriptor) { - cmdbuf.PushDescriptorSetWithTemplateKHR(*descriptor_update_template, *pipeline_layout, - 0, descriptor_data); + cmdbuf.PushDescriptorSetWithTemplateKHR(*descriptor_update_template, *pipeline_layout, 0, descriptor_data); } else { - const VkDescriptorSet descriptor_set{descriptor_allocator.Commit()}; - const vk::Device& dev{device.GetLogical()}; - dev.UpdateDescriptorSet(descriptor_set, *descriptor_update_template, descriptor_data); cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline_layout, 0, descriptor_set, nullptr); } diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index 650c8e07ed..e81b2ac1b6 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h @@ -116,7 +116,7 @@ public: maxwell3d = maxwell3d_; gpu_memory = gpu_memory_; } - + void SetFrameNumber(u64 frame) { current_frame_number = frame; } private: template bool ConfigureImpl(bool is_indexed); @@ -160,6 +160,7 @@ private: std::mutex build_mutex; std::atomic_bool is_built{false}; bool uses_push_descriptor{false}; + u64 current_frame_number{0}; }; } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_present_manager.cpp b/src/video_core/renderer_vulkan/vk_present_manager.cpp index 161f6c8b9f..0b29ad1389 100644 --- a/src/video_core/renderer_vulkan/vk_present_manager.cpp +++ b/src/video_core/renderer_vulkan/vk_present_manager.cpp @@ -412,7 +412,7 @@ void PresentManager::CopyToSwapchainImpl(Frame* frame) { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .pNext = nullptr, .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, - .dstAccessMask = 0, + .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT, .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, @@ -460,7 +460,7 @@ void PresentManager::CopyToSwapchainImpl(Frame* frame) { MakeImageCopy(frame->width, frame->height, extent.width, extent.height)); } - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, {}, + cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, {}, {}, {}, post_barriers); cmdbuf.End(); diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 70ca9583f9..71533d44e9 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -217,6 +217,7 @@ void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) { std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex}; // update engine as channel may be different. pipeline->SetEngine(maxwell3d, gpu_memory); + pipeline->SetFrameNumber(current_frame_number); if (!pipeline->Configure(is_indexed)) return; @@ -759,6 +760,7 @@ void RasterizerVulkan::FlushCommands() { } void RasterizerVulkan::TickFrame() { + current_frame_number++; draw_counter = 0; guest_descriptor_queue.TickFrame(); compute_pass_descriptor_queue.TickFrame(); diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 30780b9cbd..bcfb3ac450 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -160,7 +160,7 @@ private: void UpdateDynamicStates(); void HandleTransformFeedback(); - + u64 current_frame_number{0}; void UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& regs); void UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs); void UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs); diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index fdd2de2379..3b35e28c05 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp @@ -351,7 +351,6 @@ void Swapchain::CreateSemaphores() { void Swapchain::Destroy() { frame_index = 0; present_semaphores.clear(); - render_semaphores.clear(); swapchain.reset(); } diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 50a73ea76d..575651905e 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -1068,7 +1068,7 @@ void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src, cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, READ_BARRIER, {}, middle_out_barrier); - cmdbuf.CopyBufferToImage(copy_buffer, dst_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, vk_out_copies); + cmdbuf.CopyBufferToImage(copy_buffer, dst_image, VK_IMAGE_LAYOUT_GENERAL, vk_out_copies); cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, {}, {}, post_barriers); }); diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index cb13f28523..bd54144480 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -89,8 +89,7 @@ VK_DEFINE_HANDLE(VmaAllocator) EXTENSION(NV, VIEWPORT_ARRAY2, viewport_array2) \ EXTENSION(NV, VIEWPORT_SWIZZLE, viewport_swizzle) \ EXTENSION(EXT, DESCRIPTOR_INDEXING, descriptor_indexing) \ - EXTENSION(EXT, FILTER_CUBIC, filter_cubic) \ - EXTENSION(QCOM, FILTER_CUBIC_WEIGHTS, filter_cubic_weights) + EXTENSION(EXT, FILTER_CUBIC, filter_cubic) // Define extensions which must be supported. #define FOR_EACH_VK_MANDATORY_EXTENSION(EXTENSION_NAME) \ @@ -559,11 +558,6 @@ public: return extensions.filter_cubic; } - /// Returns true if the device supports VK_QCOM_filter_cubic_weights - bool IsQcomFilterCubicWeightsSupported() const { - return extensions.filter_cubic_weights; - } - /// Returns true if the device supports VK_EXT_line_rasterization. bool IsExtLineRasterizationSupported() const { return extensions.line_rasterization; diff --git a/src/video_core/vulkan_common/vulkan_raii.h b/src/video_core/vulkan_common/vulkan_raii.h new file mode 100644 index 0000000000..cf5e268b68 --- /dev/null +++ b/src/video_core/vulkan_common/vulkan_raii.h @@ -0,0 +1,231 @@ +// SPDX-FileCopyrightText: Copyright 2025 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include +#include +#include + +#include "common/logging/log.h" + +#include "video_core/vulkan_common/vulkan_wrapper.h" + +namespace Vulkan { + +/** + * RAII wrapper for Vulkan resources. + * Automatically manages the lifetime of Vulkan objects using RAII principles. + */ +template +class VulkanRaii { +public: + using DeleterFunc = std::function; + + // Default constructor - creates a null handle + VulkanRaii() : handle{}, deleter{}, dispatch{} {} + + // Constructor with handle and deleter + VulkanRaii(T handle_, DeleterFunc deleter_, const Dispatch& dispatch_, const char* resource_name = "Vulkan resource") + : handle{handle_}, deleter{std::move(deleter_)}, dispatch{dispatch_} { + LOG_DEBUG(Render_Vulkan, "RAII wrapper created for {}", resource_name); + } + + // Move constructor + VulkanRaii(VulkanRaii&& other) noexcept + : handle{std::exchange(other.handle, VK_NULL_HANDLE)}, + deleter{std::move(other.deleter)}, + dispatch{other.dispatch} { + } + + // Move assignment + VulkanRaii& operator=(VulkanRaii&& other) noexcept { + if (this != &other) { + cleanup(); + handle = std::exchange(other.handle, VK_NULL_HANDLE); + deleter = std::move(other.deleter); + dispatch = other.dispatch; + } + return *this; + } + + // Destructor - automatically cleans up the resource + ~VulkanRaii() { + cleanup(); + } + + // Disallow copying + VulkanRaii(const VulkanRaii&) = delete; + VulkanRaii& operator=(const VulkanRaii&) = delete; + + // Get the underlying handle + T get() const noexcept { + return handle; + } + + // Check if the handle is valid + bool valid() const noexcept { + return handle != VK_NULL_HANDLE; + } + + // Release ownership of the handle without destroying it + T release() noexcept { + return std::exchange(handle, VK_NULL_HANDLE); + } + + // Reset the handle (destroying the current one if it exists) + void reset(T new_handle = VK_NULL_HANDLE, DeleterFunc new_deleter = {}) { + cleanup(); + handle = new_handle; + deleter = std::move(new_deleter); + } + + // Implicit conversion to handle type + operator T() const noexcept { + return handle; + } + + // Dereference operator for pointer-like access + T operator->() const noexcept { + return handle; + } + +private: + // Optimized cleanup function + void cleanup() noexcept { + if (handle != VK_NULL_HANDLE && deleter) { + deleter(handle, dispatch); + handle = VK_NULL_HANDLE; + } + } + + T handle; + DeleterFunc deleter; + Dispatch dispatch; +}; + +// Common type aliases for Vulkan RAII wrappers with clearer names +using ManagedInstance = VulkanRaii; +using ManagedDevice = VulkanRaii; +using ManagedSurface = VulkanRaii; +using ManagedSwapchain = VulkanRaii; +using ManagedCommandPool = VulkanRaii; +using ManagedBuffer = VulkanRaii; +using ManagedImage = VulkanRaii; +using ManagedImageView = VulkanRaii; +using ManagedSampler = VulkanRaii; +using ManagedShaderModule = VulkanRaii; +using ManagedPipeline = VulkanRaii; +using ManagedPipelineLayout = VulkanRaii; +using ManagedDescriptorSetLayout = VulkanRaii; +using ManagedDescriptorPool = VulkanRaii; +using ManagedSemaphore = VulkanRaii; +using ManagedFence = VulkanRaii; +using ManagedDebugUtilsMessenger = VulkanRaii; + +// Helper functions to create RAII wrappers + +/** + * Creates an RAII wrapper for a Vulkan instance + */ +inline ManagedInstance MakeManagedInstance(const vk::Instance& instance, const vk::InstanceDispatch& dispatch) { + auto deleter = [](VkInstance handle, const vk::InstanceDispatch& dld) { + dld.vkDestroyInstance(handle, nullptr); + }; + return ManagedInstance(*instance, deleter, dispatch, "VkInstance"); +} + +/** + * Creates an RAII wrapper for a Vulkan device + */ +inline ManagedDevice MakeManagedDevice(const vk::Device& device, const vk::DeviceDispatch& dispatch) { + auto deleter = [](VkDevice handle, const vk::DeviceDispatch& dld) { + dld.vkDestroyDevice(handle, nullptr); + }; + return ManagedDevice(*device, deleter, dispatch, "VkDevice"); +} + +/** + * Creates an RAII wrapper for a Vulkan surface + */ +inline ManagedSurface MakeManagedSurface(const vk::SurfaceKHR& surface, const vk::Instance& instance, const vk::InstanceDispatch& dispatch) { + auto deleter = [instance_ptr = *instance](VkSurfaceKHR handle, const vk::InstanceDispatch& dld) { + dld.vkDestroySurfaceKHR(instance_ptr, handle, nullptr); + }; + return ManagedSurface(*surface, deleter, dispatch, "VkSurfaceKHR"); +} + +/** + * Creates an RAII wrapper for a Vulkan debug messenger + */ +inline ManagedDebugUtilsMessenger MakeManagedDebugUtilsMessenger(const vk::DebugUtilsMessenger& messenger, + const vk::Instance& instance, + const vk::InstanceDispatch& dispatch) { + auto deleter = [instance_ptr = *instance](VkDebugUtilsMessengerEXT handle, const vk::InstanceDispatch& dld) { + dld.vkDestroyDebugUtilsMessengerEXT(instance_ptr, handle, nullptr); + }; + return ManagedDebugUtilsMessenger(*messenger, deleter, dispatch, "VkDebugUtilsMessengerEXT"); +} + +/** + * Creates an RAII wrapper for a Vulkan swapchain + */ +inline ManagedSwapchain MakeManagedSwapchain(VkSwapchainKHR swapchain_handle, VkDevice device_handle, const vk::DeviceDispatch& dispatch) { + auto deleter = [device_handle](VkSwapchainKHR handle, const vk::DeviceDispatch& dld) { + dld.vkDestroySwapchainKHR(device_handle, handle, nullptr); + }; + return ManagedSwapchain(swapchain_handle, deleter, dispatch, "VkSwapchainKHR"); +} + +/** + * Creates an RAII wrapper for a Vulkan buffer + */ +inline ManagedBuffer MakeManagedBuffer(VkBuffer buffer_handle, VkDevice device_handle, const vk::DeviceDispatch& dispatch) { + auto deleter = [device_handle](VkBuffer handle, const vk::DeviceDispatch& dld) { + dld.vkDestroyBuffer(device_handle, handle, nullptr); + }; + return ManagedBuffer(buffer_handle, deleter, dispatch, "VkBuffer"); +} + +/** + * Creates an RAII wrapper for a Vulkan image + */ +inline ManagedImage MakeManagedImage(VkImage image_handle, VkDevice device_handle, const vk::DeviceDispatch& dispatch) { + auto deleter = [device_handle](VkImage handle, const vk::DeviceDispatch& dld) { + dld.vkDestroyImage(device_handle, handle, nullptr); + }; + return ManagedImage(image_handle, deleter, dispatch, "VkImage"); +} + +/** + * Creates an RAII wrapper for a Vulkan image view + */ +inline ManagedImageView MakeManagedImageView(VkImageView view_handle, VkDevice device_handle, const vk::DeviceDispatch& dispatch) { + auto deleter = [device_handle](VkImageView handle, const vk::DeviceDispatch& dld) { + dld.vkDestroyImageView(device_handle, handle, nullptr); + }; + return ManagedImageView(view_handle, deleter, dispatch, "VkImageView"); +} + +/** + * Creates an RAII wrapper for a Vulkan semaphore + */ +inline ManagedSemaphore MakeManagedSemaphore(VkSemaphore semaphore_handle, VkDevice device_handle, const vk::DeviceDispatch& dispatch) { + auto deleter = [device_handle](VkSemaphore handle, const vk::DeviceDispatch& dld) { + dld.vkDestroySemaphore(device_handle, handle, nullptr); + }; + return ManagedSemaphore(semaphore_handle, deleter, dispatch, "VkSemaphore"); +} + +/** + * Creates an RAII wrapper for a Vulkan fence + */ +inline ManagedFence MakeManagedFence(VkFence fence_handle, VkDevice device_handle, const vk::DeviceDispatch& dispatch) { + auto deleter = [device_handle](VkFence handle, const vk::DeviceDispatch& dld) { + dld.vkDestroyFence(device_handle, handle, nullptr); + }; + return ManagedFence(fence_handle, deleter, dispatch, "VkFence"); +} + +} // namespace Vulkan \ No newline at end of file diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp index b77d01711a..949b91499d 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.cpp +++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp @@ -12,6 +12,7 @@ #include "common/common_types.h" #include "common/logging/log.h" +#include "common/settings.h" #include "video_core/vulkan_common/vk_enum_string_helper.h" #include "video_core/vulkan_common/vma.h" #include "video_core/vulkan_common/vulkan_wrapper.h" @@ -310,7 +311,10 @@ const char* Exception::what() const noexcept { } void Destroy(VkInstance instance, const InstanceDispatch& dld) noexcept { - dld.vkDestroyInstance(instance, nullptr); + // FIXME: A double free occurs here if RAII is enabled. + if (!Settings::values.enable_raii.GetValue()) { + dld.vkDestroyInstance(instance, nullptr); + } } void Destroy(VkDevice device, const InstanceDispatch& dld) noexcept { @@ -413,7 +417,10 @@ void Destroy(VkInstance instance, VkDebugReportCallbackEXT handle, } void Destroy(VkInstance instance, VkSurfaceKHR handle, const InstanceDispatch& dld) noexcept { - dld.vkDestroySurfaceKHR(instance, handle, nullptr); + // FIXME: A double free occurs here if RAII is enabled. + if (!Settings::values.enable_raii.GetValue()) { + dld.vkDestroySurfaceKHR(instance, handle, nullptr); + } } VkResult Free(VkDevice device, VkDescriptorPool handle, Span sets, diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h index 39396b3279..6501094f05 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.h +++ b/src/video_core/vulkan_common/vulkan_wrapper.h @@ -516,7 +516,7 @@ public: } /// Returns true when there's a held object. - explicit operator bool() const noexcept { + operator bool() const noexcept { return handle != nullptr; } @@ -627,7 +627,7 @@ class Instance : public Handle { public: /// Creates a Vulkan instance. /// @throw Exception on initialization error. - [[nodiscard]] static Instance Create(u32 version, Span layers, Span extensions, + static Instance Create(u32 version, Span layers, Span extensions, InstanceDispatch& dispatch); /// Enumerates physical devices. @@ -637,12 +637,12 @@ public: /// Creates a debug callback messenger. /// @throw Exception on creation failure. - [[nodiscard]] DebugUtilsMessenger CreateDebugUtilsMessenger( + DebugUtilsMessenger CreateDebugUtilsMessenger( const VkDebugUtilsMessengerCreateInfoEXT& create_info) const; /// Creates a debug report callback. /// @throw Exception on creation failure. - [[nodiscard]] DebugReportCallback CreateDebugReportCallback( + DebugReportCallback CreateDebugReportCallback( const VkDebugReportCallbackCreateInfoEXT& create_info) const; /// Returns dispatch table. @@ -986,60 +986,58 @@ class Device : public Handle { using Handle::Handle; public: - [[nodiscard]] static Device Create(VkPhysicalDevice physical_device, - Span queues_ci, - Span enabled_extensions, const void* next, - DeviceDispatch& dispatch); + static Device Create(VkPhysicalDevice physical_device, Span queues_ci, + Span enabled_extensions, const void* next, + DeviceDispatch& dispatch); - [[nodiscard]] Queue GetQueue(u32 family_index) const noexcept; + Queue GetQueue(u32 family_index) const noexcept; - [[nodiscard]] BufferView CreateBufferView(const VkBufferViewCreateInfo& ci) const; + BufferView CreateBufferView(const VkBufferViewCreateInfo& ci) const; - [[nodiscard]] ImageView CreateImageView(const VkImageViewCreateInfo& ci) const; + ImageView CreateImageView(const VkImageViewCreateInfo& ci) const; - [[nodiscard]] Semaphore CreateSemaphore() const; + Semaphore CreateSemaphore() const; - [[nodiscard]] Semaphore CreateSemaphore(const VkSemaphoreCreateInfo& ci) const; + Semaphore CreateSemaphore(const VkSemaphoreCreateInfo& ci) const; - [[nodiscard]] Fence CreateFence(const VkFenceCreateInfo& ci) const; + Fence CreateFence(const VkFenceCreateInfo& ci) const; - [[nodiscard]] DescriptorPool CreateDescriptorPool(const VkDescriptorPoolCreateInfo& ci) const; + DescriptorPool CreateDescriptorPool(const VkDescriptorPoolCreateInfo& ci) const; - [[nodiscard]] RenderPass CreateRenderPass(const VkRenderPassCreateInfo& ci) const; + RenderPass CreateRenderPass(const VkRenderPassCreateInfo& ci) const; - [[nodiscard]] DescriptorSetLayout CreateDescriptorSetLayout( - const VkDescriptorSetLayoutCreateInfo& ci) const; + DescriptorSetLayout CreateDescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo& ci) const; - [[nodiscard]] PipelineCache CreatePipelineCache(const VkPipelineCacheCreateInfo& ci) const; + PipelineCache CreatePipelineCache(const VkPipelineCacheCreateInfo& ci) const; - [[nodiscard]] PipelineLayout CreatePipelineLayout(const VkPipelineLayoutCreateInfo& ci) const; + PipelineLayout CreatePipelineLayout(const VkPipelineLayoutCreateInfo& ci) const; - [[nodiscard]] Pipeline CreateGraphicsPipeline(const VkGraphicsPipelineCreateInfo& ci, - VkPipelineCache cache = nullptr) const; + Pipeline CreateGraphicsPipeline(const VkGraphicsPipelineCreateInfo& ci, + VkPipelineCache cache = nullptr) const; - [[nodiscard]] Pipeline CreateComputePipeline(const VkComputePipelineCreateInfo& ci, - VkPipelineCache cache = nullptr) const; + Pipeline CreateComputePipeline(const VkComputePipelineCreateInfo& ci, + VkPipelineCache cache = nullptr) const; - [[nodiscard]] Sampler CreateSampler(const VkSamplerCreateInfo& ci) const; + Sampler CreateSampler(const VkSamplerCreateInfo& ci) const; - [[nodiscard]] Framebuffer CreateFramebuffer(const VkFramebufferCreateInfo& ci) const; + Framebuffer CreateFramebuffer(const VkFramebufferCreateInfo& ci) const; - [[nodiscard]] CommandPool CreateCommandPool(const VkCommandPoolCreateInfo& ci) const; + CommandPool CreateCommandPool(const VkCommandPoolCreateInfo& ci) const; - [[nodiscard]] DescriptorUpdateTemplate CreateDescriptorUpdateTemplate( + DescriptorUpdateTemplate CreateDescriptorUpdateTemplate( const VkDescriptorUpdateTemplateCreateInfo& ci) const; - [[nodiscard]] QueryPool CreateQueryPool(const VkQueryPoolCreateInfo& ci) const; + QueryPool CreateQueryPool(const VkQueryPoolCreateInfo& ci) const; - [[nodiscard]] ShaderModule CreateShaderModule(const VkShaderModuleCreateInfo& ci) const; + ShaderModule CreateShaderModule(const VkShaderModuleCreateInfo& ci) const; - [[nodiscard]] Event CreateEvent() const; + Event CreateEvent() const; - [[nodiscard]] SwapchainKHR CreateSwapchainKHR(const VkSwapchainCreateInfoKHR& ci) const; + SwapchainKHR CreateSwapchainKHR(const VkSwapchainCreateInfoKHR& ci) const; - [[nodiscard]] DeviceMemory TryAllocateMemory(const VkMemoryAllocateInfo& ai) const noexcept; + DeviceMemory TryAllocateMemory(const VkMemoryAllocateInfo& ai) const noexcept; - [[nodiscard]] DeviceMemory AllocateMemory(const VkMemoryAllocateInfo& ai) const; + DeviceMemory AllocateMemory(const VkMemoryAllocateInfo& ai) const; VkMemoryRequirements GetBufferMemoryRequirements(VkBuffer buffer, void* pnext = nullptr) const noexcept; diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp index b825348760..18f629f639 100644 --- a/src/yuzu/configuration/configure_debug.cpp +++ b/src/yuzu/configuration/configure_debug.cpp @@ -83,7 +83,8 @@ void ConfigureDebug::SetConfiguration() { #ifdef YUZU_USE_QT_WEB_ENGINE ui->disable_web_applet->setChecked(UISettings::values.disable_web_applet.GetValue()); #else - ui->disable_web_applet->setVisible(false); + ui->disable_web_applet->setEnabled(false); + ui->disable_web_applet->setText(tr("Web applet not compiled")); #endif } diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 44ed29f141..901a39cc9f 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -545,9 +545,6 @@ GMainWindow::GMainWindow(bool has_broken_vulkan) // Gen keys if necessary OnCheckFirmwareDecryption(); - // Check for orphaned profiles and reset profile data if necessary - QtCommon::Content::FixProfiles(); - game_list->LoadCompatibilityList(); // force reload on first load to ensure add-ons get updated game_list->PopulateAsync(UISettings::values.game_dirs); @@ -3950,7 +3947,7 @@ void GMainWindow::OnToggleStatusBar() { void GMainWindow::OnGameListRefresh() { // Resets metadata cache and reloads - QtCommon::Game::ResetMetadata(false); + QtCommon::Game::ResetMetadata(); game_list->RefreshGameDirectory(); SetFirmwareVersion(); } diff --git a/src/yuzu/migration_worker.cpp b/src/yuzu/migration_worker.cpp index 95f205ec0c..42ec006026 100644 --- a/src/yuzu/migration_worker.cpp +++ b/src/yuzu/migration_worker.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "common/fs/path_util.h"