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 dae9297fd7..ca3309245e 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 @@ -38,7 +38,6 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting { RENDERER_VERTEX_INPUT_DYNAMIC_STATE("vertex_input_dynamic_state"), RENDERER_SAMPLE_SHADING("sample_shading"), RENDERER_FRAME_GEN("frame_gen"), - RENDERER_FRAME_GEN_FP16("frame_gen_fp16"), RENDERER_FRAME_GEN_FLOW_SCALE_AUTO("frame_gen_flow_scale_auto"), GPU_UNSWIZZLE_ENABLED("gpu_unswizzle_enabled"), PICTURE_IN_PICTURE("picture_in_picture"), 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 8d78dda333..3f38831a17 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 @@ -123,8 +123,7 @@ abstract class SettingsItem( IntSetting.RENDERER_FRAME_GEN_TARGET_RATE.key, IntSetting.RENDERER_FRAME_GEN_QUEUE_TARGET.key, BooleanSetting.RENDERER_FRAME_GEN_FLOW_SCALE_AUTO.key, - IntSetting.RENDERER_FRAME_GEN_FLOW_SCALE.key, - BooleanSetting.RENDERER_FRAME_GEN_FP16.key + IntSetting.RENDERER_FRAME_GEN_FLOW_SCALE.key ) const val TYPE_HEADER = 0 @@ -708,13 +707,6 @@ abstract class SettingsItem( units = "%" ) ) - put( - SwitchSetting( - BooleanSetting.RENDERER_FRAME_GEN_FP16, - titleId = R.string.frame_gen_fp16, - descriptionId = R.string.frame_gen_fp16_description - ) - ) put( SingleChoiceSetting( IntSetting.RENDERER_SCREEN_LAYOUT, 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 c50649277c..ca282ba159 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 @@ -124,7 +124,6 @@ class SettingsFragmentPresenter( ) { add(IntSetting.RENDERER_FRAME_GEN_FLOW_SCALE.key) } - add(BooleanSetting.RENDERER_FRAME_GEN_FP16.key) } } diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index 423edc2c1b..746b00ad11 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp @@ -1168,7 +1168,7 @@ VkPhysicalDeviceProperties GetVulkanDeviceProperties() { return physical_device.GetProperties(); } -bool GetVulkanMemoryModelSupport() { +bool GetFrameGenerationSupport() { Common::DynamicLibrary library; if (!library.Open("libvulkan.so")) { return false; @@ -1183,9 +1183,13 @@ bool GetVulkanMemoryModelSupport() { const Vulkan::vk::PhysicalDevice physical_device(physical_devices[0], dld); + VkPhysicalDeviceShaderFloat16Int8Features float16_int8{ + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES, + .pNext = nullptr, + }; VkPhysicalDeviceVulkanMemoryModelFeatures memory_model{ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES, - .pNext = nullptr, + .pNext = &float16_int8, }; VkPhysicalDeviceFeatures2 features{ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, @@ -1193,7 +1197,7 @@ bool GetVulkanMemoryModelSupport() { }; physical_device.GetFeatures2(features); - return memory_model.vulkanMemoryModel == VK_TRUE; + return memory_model.vulkanMemoryModel == VK_TRUE && float16_int8.shaderFloat16 == VK_TRUE; } } // namespace @@ -1272,7 +1276,7 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getVulkanApiVersion(JNIEnv* env, j jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_supportsFrameGeneration(JNIEnv* env, jobject jobj) { try { - return static_cast(GetVulkanMemoryModelSupport()); + return static_cast(GetFrameGenerationSupport()); } catch (...) { return static_cast(false); } 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 5543ea732d..9895ec011c 100644 --- a/src/android/app/src/main/res/values-ar/strings.xml +++ b/src/android/app/src/main/res/values-ar/strings.xml @@ -314,8 +314,6 @@ قم بتقدير الحركة بناءً على الدقة التي تعرضها اللعبة فعليًّا، بدلاً من الإخراج الذي تم رفع دقته. ولا يؤثر ذلك على الدقة بأي شكل، لأن رفع الدقة لا يضيف أي تفاصيل تتعلق بالحركة. دقة تقدير الحركة دقة مسار التدفق البصري، كجزء من الناتج. ويُعد خفض هذه القيمة أرخص طريقة لاستعادة الأداء. - مُظلِّلات نصف الدقة - استخدم نسخة التظليل 16 بت. يتم التراجع تلقائيًا إلى الخيار البديل في حالة عدم توفرها في برنامج التشغيل أو الملف. توليد الإطار غير متاح لا يدعم برنامج تشغيل وحدة معالجة الرسومات هذا نموذج ذاكرة Vulkan، الذي تتطلبه برامج التظليل الخاصة بـ«Lossless Scaling». اختياري. قم بتوفير ملف Lossless.dll الخاص بك لتمكين إنشاء الإطارات لاحقًا 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 2fecc7a82f..10031b7441 100644 --- a/src/android/app/src/main/res/values-es/strings.xml +++ b/src/android/app/src/main/res/values-es/strings.xml @@ -304,7 +304,6 @@ Latencia más baja (Sin búfer) Equilibrado (1 fotograma) Más suave (2 fotogramas) - Sombreadores de media precisión Generación de fotogramas no disponbile Instalar Lossless.dll Seleccionar una copia diferente de Lossless.dll 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 e4621ec308..9a3c97de9d 100644 --- a/src/android/app/src/main/res/values-ru/strings.xml +++ b/src/android/app/src/main/res/values-ru/strings.xml @@ -308,8 +308,6 @@ Оценивать движение в разрешении, которое игра действительно рендерит, вместо масштабированного вывода. Ничего не стоит в точности, так как масштабирование не добавляет деталей движения. Разрешение оценки движения Разрешение прохода оптического потока в долях от выходного разрешения. Его понижение — самый дешёвый способ вернуть производительность. - Шейдеры половинной точности - Использовать 16-битную версию шейдеров. Автоматически переключается на обычную, если драйвер или файл не поддерживают её. Генерация кадров недоступна Драйвер ГПУ не поддерживает модель памяти Vulkan, требуемую шейдерами Lossless Scaling. Опционально. Укажите свой Lossless.dll для включения генерации кадров позже. 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 f6dc99ae67..03b730f1ed 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 @@ -314,8 +314,6 @@ 在游戏实际渲染的分辨率下估算运动,而不是在放大后的输出上。不会影响精确性,因为放大并不会增加运动细节。 运动预估分辨率 光流通道的分辨率,以输出的比例表示。降低它是提升性能最经济的做法。 - 半精度着色器 - 使用 16 位着色器变体。如果驱动或文件不支持会自动回退。 帧生成不可用 这个 GPU 驱动不支持无损缩放着色器所需的 Vulkan 内存模型。 作为可选项。请提供您自己的 Lossless.dll 以便在之后可以启用帧生成。 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 d42154280f..63eac94759 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 @@ -314,8 +314,6 @@ 以遊戲實際渲染的解析度而非升頻後的輸出進行運動預測。由於升頻後不會增加任何動態細節,因此不會影響準確度 運動預測解析度 光流處理的解析度,以輸出解析度的比例表示。降低此設定值是減少效能負載最有效的方法 - 半準確著色器 - 使用16位元著色器。如果驅動程式或著色器檔案不支援則會自動切換成其它版本 無法使用影格生成 Lossless Scaling 的著色器需要 Vulkan 記憶體模型,所選的驅動程式不支援該功能 可選擇安裝自己擁有的 Lossless.dll 以在之後啟用影格生成功能 diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 8f5b905dd2..730f6bbade 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -347,17 +347,15 @@ Estimate motion at the resolution the game actually renders instead of the upscaled output. Costs nothing in accuracy, since upscaling adds no motion detail. Motion estimation resolution Resolution of the optical flow pass, as a fraction of the output. Lowering it is the cheapest way to reclaim performance. - Half precision shaders - Use the 16-bit shader variant. Falls back automatically if the driver or the file lacks it. Frame generation unavailable - This GPU driver does not support the Vulkan memory model, which the Lossless Scaling shaders require. + This GPU driver lacks the Vulkan memory model or half precision (float16) support that the Lossless Scaling shaders require. Optional. Provide your own Lossless.dll to enable frame generation later Install Lossless.dll Frame generation needs your own legal copy of Lossless.dll from Lossless Scaling Select a different copy of Lossless.dll Frame generation Supported - Unsupported (no Vulkan memory model) + Unsupported (no Vulkan memory model or float16) Lossless Scaling Provide your own copy of Lossless.dll to enable frame generation Installed diff --git a/src/common/settings.h b/src/common/settings.h index 6b60d633a5..c1c2d4f0df 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -459,7 +459,7 @@ struct Values { &frame_gen}; SwitchableSetting frame_gen_queue_target{linkage, - 1, + 0, 0, 2, "frame_gen_queue_target", @@ -469,9 +469,6 @@ struct Values { false, &frame_gen}; - SwitchableSetting frame_gen_fp16{linkage, true, "frame_gen_fp16", Category::Renderer, - Specialization::Default, true, false, &frame_gen}; - SwitchableSetting frame_gen_dump_flow{linkage, false, "frame_gen_dump_flow", Category::Renderer}; diff --git a/src/video_core/frame_gen/lossless_dll.cpp b/src/video_core/frame_gen/lossless_dll.cpp index 5d2d08ffb3..6be1e5530f 100644 --- a/src/video_core/frame_gen/lossless_dll.cpp +++ b/src/video_core/frame_gen/lossless_dll.cpp @@ -45,7 +45,7 @@ constexpr u32 PERFORMANCE_SHADER_ID_FIRST = 280; constexpr u32 PERFORMANCE_SHADER_ID_LAST = 302; constexpr u32 CACHE_MAGIC = 0x4746534C; -constexpr u32 CACHE_VERSION = 2; +constexpr u32 CACHE_VERSION = 3; struct CacheHeader { u32 magic; @@ -53,7 +53,6 @@ struct CacheHeader { u64 source_size; u64 source_hash; u32 module_count; - u32 variant; }; struct Section { @@ -277,41 +276,19 @@ template return std::ranges::all_of(ids, [&](u32 id) { return resources.contains(id); }); } -[[nodiscard]] u32 VariantOffset(ShaderVariant variant) { - return variant == ShaderVariant::NativeFp16 ? PerformanceShader::NATIVE_FP16_OFFSET - : PerformanceShader::NATIVE_FP32_OFFSET; -} - template -[[nodiscard]] bool HasNativeVariant(const Map& resources, ShaderVariant variant) { - const u32 offset = VariantOffset(variant); +[[nodiscard]] bool HasNativeShaders(const Map& resources) { return std::ranges::all_of(PerformanceShaderIds(), [&](u32 id) { - const auto hit = resources.find(id + offset); + const auto hit = resources.find(id + PerformanceShader::NATIVE_FP16_OFFSET); return hit != resources.end() && IsSpirvModule(hit->second); }); } -[[nodiscard]] std::optional SelectVariant(const ResourceSpans& resources, - bool allow_fp16, bool prefer_fp16) { - if (prefer_fp16 && HasNativeVariant(resources, ShaderVariant::NativeFp16)) { - return ShaderVariant::NativeFp16; - } - if (HasNativeVariant(resources, ShaderVariant::NativeFp32)) { - return ShaderVariant::NativeFp32; - } - if (allow_fp16 && HasNativeVariant(resources, ShaderVariant::NativeFp16)) { - return ShaderVariant::NativeFp16; - } - return std::nullopt; -} - [[nodiscard]] LosslessStatus TranslateAll(const ResourceSpans& resources, - ShaderModules& out_modules, - ShaderVariant variant) { - const u32 offset = VariantOffset(variant); + ShaderModules& out_modules) { out_modules.clear(); for (const u32 id : PerformanceShaderIds()) { - const auto hit = resources.find(id + offset); + const auto hit = resources.find(id + PerformanceShader::NATIVE_FP16_OFFSET); if (hit == resources.end()) { return LosslessStatus::MissingShaders; } @@ -343,7 +320,7 @@ template } [[nodiscard]] bool ReadShaderCache(const std::filesystem::path& path, u64 source_size, - u64 source_hash, u32 variant, ShaderModules& out_modules) { + u64 source_hash, ShaderModules& out_modules) { if (!Common::FS::Exists(path)) { return false; } @@ -355,8 +332,7 @@ template return false; } if (header.magic != CACHE_MAGIC || header.version != CACHE_VERSION || - header.source_size != source_size || header.source_hash != source_hash || - header.variant != variant) { + header.source_size != source_size || header.source_hash != source_hash) { return false; } @@ -433,8 +409,10 @@ template return LosslessStatus::MissingShaders; } - return HasPerformanceShaders(out_resources) ? LosslessStatus::Ok - : LosslessStatus::MissingShaders; + if (!HasNativeShaders(out_resources)) { + return LosslessStatus::MissingShaders; + } + return LosslessStatus::Ok; } } // Anonymous namespace @@ -483,7 +461,7 @@ LosslessStatus GetInstalledLosslessStatus() { return ValidateLosslessDll(GetLosslessDllPath()); } -LosslessStatus LoadShaderModules(ShaderModules& out_modules, bool allow_fp16, bool prefer_fp16) { +LosslessStatus LoadShaderModules(ShaderModules& out_modules) { std::vector image; const LosslessStatus read_status = ReadImageFile(GetLosslessDllPath(), image); if (read_status != LosslessStatus::Ok) { @@ -501,17 +479,11 @@ LosslessStatus LoadShaderModules(ShaderModules& out_modules, bool allow_fp16, bo return parse_status; } - const std::optional variant = SelectVariant(spans, allow_fp16, prefer_fp16); - if (!variant) { - return LosslessStatus::MissingShaders; - } - - if (ReadShaderCache(cache_path, source_size, source_hash, static_cast(*variant), - out_modules)) { + if (ReadShaderCache(cache_path, source_size, source_hash, out_modules)) { return LosslessStatus::Ok; } - const LosslessStatus translate_status = TranslateAll(spans, out_modules, *variant); + const LosslessStatus translate_status = TranslateAll(spans, out_modules); if (translate_status != LosslessStatus::Ok) { return translate_status; } @@ -522,7 +494,6 @@ LosslessStatus LoadShaderModules(ShaderModules& out_modules, bool allow_fp16, bo .source_size = source_size, .source_hash = source_hash, .module_count = static_cast(out_modules.size()), - .variant = static_cast(*variant), }; if (!WriteShaderCache(cache_path, header, out_modules)) { void(Common::FS::RemoveFile(cache_path)); @@ -534,7 +505,7 @@ LosslessStatus LoadShaderModules(ShaderModules& out_modules, bool allow_fp16, bo LosslessStatus BuildShaderCache() { ShaderModules modules; - return LoadShaderModules(modules, true); + return LoadShaderModules(modules); } bool RemoveInstalledLosslessDll() { diff --git a/src/video_core/frame_gen/lossless_dll.h b/src/video_core/frame_gen/lossless_dll.h index 1d583d008f..53e4974521 100644 --- a/src/video_core/frame_gen/lossless_dll.h +++ b/src/video_core/frame_gen/lossless_dll.h @@ -28,11 +28,6 @@ enum class LosslessStatus : u32 { using ShaderResources = std::map>; using ShaderModules = std::map>; -enum class ShaderVariant : u32 { - NativeFp32 = 1, - NativeFp16 = 2, -}; - namespace PerformanceShader { constexpr u32 MIPMAPS = 255; constexpr u32 GENERATE = 256; @@ -42,7 +37,6 @@ constexpr std::array GAMMA{280, 282, 283, 284, 285}; constexpr std::array DELTA{280, 286, 287, 288, 289, 281, 294, 295, 296, 297}; constexpr u32 NATIVE_FP16_OFFSET = 49; -constexpr u32 NATIVE_FP32_OFFSET = 98; } // namespace PerformanceShader [[nodiscard]] std::filesystem::path GetLosslessDllPath(); @@ -58,9 +52,7 @@ constexpr u32 NATIVE_FP32_OFFSET = 98; [[nodiscard]] LosslessStatus BuildShaderCache(); -[[nodiscard]] LosslessStatus LoadShaderModules(ShaderModules& out_modules, - bool allow_fp16 = false, - bool prefer_fp16 = false); +[[nodiscard]] LosslessStatus LoadShaderModules(ShaderModules& out_modules); bool RemoveInstalledLosslessDll(); diff --git a/src/video_core/renderer_vulkan/present/lsfg_shaders.cpp b/src/video_core/renderer_vulkan/present/lsfg_shaders.cpp index aafe0d6419..51c7e4c106 100644 --- a/src/video_core/renderer_vulkan/present/lsfg_shaders.cpp +++ b/src/video_core/renderer_vulkan/present/lsfg_shaders.cpp @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later -#include "common/settings.h" #include "video_core/frame_gen/lossless_dll.h" #include "video_core/renderer_vulkan/present/lsfg_shaders.h" #include "video_core/renderer_vulkan/present/util.h" @@ -10,16 +9,13 @@ namespace Vulkan { LsfgShaders::LsfgShaders(const Device& device) { - if (!device.IsVulkanMemoryModelSupported() || !device.HasNullDescriptor()) { + if (!device.IsVulkanMemoryModelSupported() || !device.HasNullDescriptor() || + !device.IsFloat16Supported()) { return; } - const bool allow_fp16 = device.IsFloat16Supported(); - const bool prefer_fp16 = allow_fp16 && Settings::values.frame_gen_fp16.GetValue(); - VideoCore::FrameGen::ShaderModules code; - if (VideoCore::FrameGen::LoadShaderModules(code, allow_fp16, prefer_fp16) != - VideoCore::FrameGen::LosslessStatus::Ok) { + if (VideoCore::FrameGen::LoadShaderModules(code) != VideoCore::FrameGen::LosslessStatus::Ok) { return; }