diff --git a/src/Ryujinx.Common/GraphicsDriver/DriverUtilities.cs b/src/Ryujinx.Common/GraphicsDriver/DriverUtilities.cs index 7fe2a4f024..83bc8d555b 100644 --- a/src/Ryujinx.Common/GraphicsDriver/DriverUtilities.cs +++ b/src/Ryujinx.Common/GraphicsDriver/DriverUtilities.cs @@ -11,7 +11,19 @@ namespace Ryujinx.Common.GraphicsDriver try { - NVThreadedOptimization.SetThreadedOptimization(enabled); + NVDriverHelper.SetThreadedOptimization(enabled); + } + catch + { + // NVAPI is not available, or couldn't change the application profile. + } + } + + public static void ToggleDxgiSwapchain(bool enabled) + { + try + { + NVDriverHelper.SetDxgiSwapchain(enabled); } catch { diff --git a/src/Ryujinx.Common/GraphicsDriver/NVAPI/Nvapi.cs b/src/Ryujinx.Common/GraphicsDriver/NVAPI/Nvapi.cs index 985e5e6d3a..71ea62f47a 100644 --- a/src/Ryujinx.Common/GraphicsDriver/NVAPI/Nvapi.cs +++ b/src/Ryujinx.Common/GraphicsDriver/NVAPI/Nvapi.cs @@ -1,11 +1,22 @@ namespace Ryujinx.Common.GraphicsDriver.NVAPI { - enum Nvapi : uint + enum NvapiSettingID : uint { OglThreadControlId = 0x20C1221E, - + OglCplPreferDxPresentId = 0x20D690F8, + } + enum OglThreadControl : uint + { OglThreadControlDefault = 0, OglThreadControlEnable = 1, OglThreadControlDisable = 2, } + + // Only present in driver versions >= 526.47 + enum OglCplDxPresent : uint + { + OglCplPreferDxPresentDisable = 0, + OglCplPreferDxPresentEnable = 1, + OglCplPreferDxPresentDefault = 2, + } } diff --git a/src/Ryujinx.Common/GraphicsDriver/NVAPI/NvdrsSetting.cs b/src/Ryujinx.Common/GraphicsDriver/NVAPI/NvdrsSetting.cs index a36781bafc..9e355c33c9 100644 --- a/src/Ryujinx.Common/GraphicsDriver/NVAPI/NvdrsSetting.cs +++ b/src/Ryujinx.Common/GraphicsDriver/NVAPI/NvdrsSetting.cs @@ -26,7 +26,7 @@ namespace Ryujinx.Common.GraphicsDriver.NVAPI [FieldOffset(0x4)] public NvapiUnicodeString SettingName; [FieldOffset(0x1004)] - public Nvapi SettingId; + public NvapiSettingID SettingId; [FieldOffset(0x1008)] public NvdrsSettingType SettingType; [FieldOffset(0x100C)] diff --git a/src/Ryujinx.Common/GraphicsDriver/NVThreadedOptimization.cs b/src/Ryujinx.Common/GraphicsDriver/NVDriverHelper.cs similarity index 79% rename from src/Ryujinx.Common/GraphicsDriver/NVThreadedOptimization.cs rename to src/Ryujinx.Common/GraphicsDriver/NVDriverHelper.cs index f7b11783d5..bc28f4ec87 100644 --- a/src/Ryujinx.Common/GraphicsDriver/NVThreadedOptimization.cs +++ b/src/Ryujinx.Common/GraphicsDriver/NVDriverHelper.cs @@ -1,11 +1,13 @@ using Ryujinx.Common.GraphicsDriver.NVAPI; using System; +using System.ComponentModel; +using System.Dynamic; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace Ryujinx.Common.GraphicsDriver { - static partial class NVThreadedOptimization + static partial class NVDriverHelper { private const string ProfileName = "Ryujinx Nvidia Profile"; @@ -49,6 +51,9 @@ namespace Ryujinx.Common.GraphicsDriver private delegate int NvAPI_DRS_DestroySessionDelegate(IntPtr handle); private static NvAPI_DRS_DestroySessionDelegate NvAPI_DRS_DestroySession; + private static IntPtr _handle; + private static nint _profileHandle; + private static bool _initialized; private static void Check(int status) @@ -80,17 +85,8 @@ namespace Ryujinx.Common.GraphicsDriver } } - private static uint MakeVersion(uint version) where T : unmanaged + private static void SetupNvProfile() { - return (uint)Unsafe.SizeOf() | version << 16; - } - - public static void SetThreadedOptimization(bool enabled) - { - Initialize(); - - uint targetValue = (uint)(enabled ? Nvapi.OglThreadControlEnable : Nvapi.OglThreadControlDisable); - Check(NvAPI_Initialize()); Check(NvAPI_DRS_CreateSession(out IntPtr handle)); @@ -98,7 +94,6 @@ namespace Ryujinx.Common.GraphicsDriver Check(NvAPI_DRS_LoadSettings(handle)); // Check if the profile already exists. - int status = NvAPI_DRS_FindProfileByName(handle, new NvapiUnicodeString(ProfileName), out nint profileHandle); if (status != 0) @@ -126,10 +121,27 @@ namespace Ryujinx.Common.GraphicsDriver Check(NvAPI_DRS_CreateApplication(handle, profileHandle, ref application)); } + _handle = handle; + _profileHandle = profileHandle; + } + + private static uint MakeVersion(uint version) where T : unmanaged + { + return (uint)Unsafe.SizeOf() | version << 16; + } + + public static void SetThreadedOptimization(bool enabled) + { + Initialize(); + + SetupNvProfile(); + + uint targetValue = (uint)(enabled ? OglThreadControl.OglThreadControlEnable : OglThreadControl.OglThreadControlDisable); + NvdrsSetting setting = new() { Version = MakeVersion(1), - SettingId = Nvapi.OglThreadControlId, + SettingId = NvapiSettingID.OglThreadControlId, SettingType = NvdrsSettingType.NvdrsDwordType, SettingLocation = NvdrsSettingLocation.NvdrsCurrentProfileLocation, IsCurrentPredefined = 0, @@ -138,11 +150,38 @@ namespace Ryujinx.Common.GraphicsDriver PredefinedValue = targetValue, }; - Check(NvAPI_DRS_SetSetting(handle, profileHandle, ref setting)); + Check(NvAPI_DRS_SetSetting(_handle, _profileHandle, ref setting)); - Check(NvAPI_DRS_SaveSettings(handle)); + Check(NvAPI_DRS_SaveSettings(_handle)); - NvAPI_DRS_DestroySession(handle); + NvAPI_DRS_DestroySession(_handle); + } + + public static void SetDxgiSwapchain(bool enabled) + { + Initialize(); + + SetupNvProfile(); + + uint targetValue = (uint)(enabled ? OglCplDxPresent.OglCplPreferDxPresentEnable : OglCplDxPresent.OglCplPreferDxPresentDisable); + + NvdrsSetting setting = new() + { + Version = MakeVersion(1), + SettingId = NvapiSettingID.OglCplPreferDxPresentId, + SettingType = NvdrsSettingType.NvdrsDwordType, + SettingLocation = NvdrsSettingLocation.NvdrsCurrentProfileLocation, + IsCurrentPredefined = 0, + IsPredefinedValid = 0, + CurrentValue = targetValue, + PredefinedValue = targetValue, + }; + + Check(NvAPI_DRS_SetSetting(_handle, _profileHandle, ref setting)); + + Check(NvAPI_DRS_SaveSettings(_handle)); + + NvAPI_DRS_DestroySession(_handle); } private static T NvAPI_Delegate(uint id) where T : class diff --git a/src/Ryujinx/Program.cs b/src/Ryujinx/Program.cs index 89e895e81b..45e2a0c40d 100644 --- a/src/Ryujinx/Program.cs +++ b/src/Ryujinx/Program.cs @@ -114,6 +114,9 @@ namespace Ryujinx.Ava // Enable OGL multithreading on the driver, when available. DriverUtilities.ToggleOGLThreading(ConfigurationState.Instance.Graphics.BackendThreading == BackendThreading.Off); + // Enable Dxgi present on the driver, when available. + DriverUtilities.ToggleDxgiSwapchain(true); + // Check if keys exists. if (!File.Exists(Path.Combine(AppDataManager.KeysDirPath, "prod.keys"))) {