NVThreadedOptimization.cs 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. using Ryujinx.Common.GraphicsDriver.NVAPI;
  2. using System;
  3. using System.Runtime.CompilerServices;
  4. using System.Runtime.InteropServices;
  5. namespace Ryujinx.Common.GraphicsDriver
  6. {
  7. static class NVThreadedOptimization
  8. {
  9. private const string ProfileName = "Ryujinx Nvidia Profile";
  10. private const uint NvAPI_Initialize_ID = 0x0150E828;
  11. private const uint NvAPI_DRS_CreateSession_ID = 0x0694D52E;
  12. private const uint NvAPI_DRS_LoadSettings_ID = 0x375DBD6B;
  13. private const uint NvAPI_DRS_FindProfileByName_ID = 0x7E4A9A0B;
  14. private const uint NvAPI_DRS_CreateProfile_ID = 0x0CC176068;
  15. private const uint NvAPI_DRS_CreateApplication_ID = 0x4347A9DE;
  16. private const uint NvAPI_DRS_SetSetting_ID = 0x577DD202;
  17. private const uint NvAPI_DRS_SaveSettings_ID = 0xFCBC7E14;
  18. private const uint NvAPI_DRS_DestroySession_ID = 0x0DAD9CFF8;
  19. [DllImport("nvapi64")]
  20. private static extern IntPtr nvapi_QueryInterface(uint id);
  21. private delegate int NvAPI_InitializeDelegate();
  22. private static NvAPI_InitializeDelegate NvAPI_Initialize;
  23. private delegate int NvAPI_DRS_CreateSessionDelegate(out IntPtr handle);
  24. private static NvAPI_DRS_CreateSessionDelegate NvAPI_DRS_CreateSession;
  25. private delegate int NvAPI_DRS_LoadSettingsDelegate(IntPtr handle);
  26. private static NvAPI_DRS_LoadSettingsDelegate NvAPI_DRS_LoadSettings;
  27. private delegate int NvAPI_DRS_FindProfileByNameDelegate(IntPtr handle, NvapiUnicodeString profileName, out IntPtr profileHandle);
  28. private static NvAPI_DRS_FindProfileByNameDelegate NvAPI_DRS_FindProfileByName;
  29. private delegate int NvAPI_DRS_CreateProfileDelegate(IntPtr handle, ref NvdrsProfile profileInfo, out IntPtr profileHandle);
  30. private static NvAPI_DRS_CreateProfileDelegate NvAPI_DRS_CreateProfile;
  31. private delegate int NvAPI_DRS_CreateApplicationDelegate(IntPtr handle, IntPtr profileHandle, ref NvdrsApplicationV4 app);
  32. private static NvAPI_DRS_CreateApplicationDelegate NvAPI_DRS_CreateApplication;
  33. private delegate int NvAPI_DRS_SetSettingDelegate(IntPtr handle, IntPtr profileHandle, ref NvdrsSetting setting);
  34. private static NvAPI_DRS_SetSettingDelegate NvAPI_DRS_SetSetting;
  35. private delegate int NvAPI_DRS_SaveSettingsDelegate(IntPtr handle);
  36. private static NvAPI_DRS_SaveSettingsDelegate NvAPI_DRS_SaveSettings;
  37. private delegate int NvAPI_DRS_DestroySessionDelegate(IntPtr handle);
  38. private static NvAPI_DRS_DestroySessionDelegate NvAPI_DRS_DestroySession;
  39. private static bool _initialized;
  40. private static void Check(int status)
  41. {
  42. if (status != 0)
  43. {
  44. throw new Exception($"NVAPI Error: {status}");
  45. }
  46. }
  47. private static void Initialize()
  48. {
  49. if (!_initialized)
  50. {
  51. NvAPI_Initialize = NvAPI_Delegate<NvAPI_InitializeDelegate>(NvAPI_Initialize_ID);
  52. Check(NvAPI_Initialize());
  53. NvAPI_DRS_CreateSession = NvAPI_Delegate<NvAPI_DRS_CreateSessionDelegate>(NvAPI_DRS_CreateSession_ID);
  54. NvAPI_DRS_LoadSettings = NvAPI_Delegate<NvAPI_DRS_LoadSettingsDelegate>(NvAPI_DRS_LoadSettings_ID);
  55. NvAPI_DRS_FindProfileByName = NvAPI_Delegate<NvAPI_DRS_FindProfileByNameDelegate>(NvAPI_DRS_FindProfileByName_ID);
  56. NvAPI_DRS_CreateProfile = NvAPI_Delegate<NvAPI_DRS_CreateProfileDelegate>(NvAPI_DRS_CreateProfile_ID);
  57. NvAPI_DRS_CreateApplication = NvAPI_Delegate<NvAPI_DRS_CreateApplicationDelegate>(NvAPI_DRS_CreateApplication_ID);
  58. NvAPI_DRS_SetSetting = NvAPI_Delegate<NvAPI_DRS_SetSettingDelegate>(NvAPI_DRS_SetSetting_ID);
  59. NvAPI_DRS_SaveSettings = NvAPI_Delegate<NvAPI_DRS_SaveSettingsDelegate>(NvAPI_DRS_SaveSettings_ID);
  60. NvAPI_DRS_DestroySession = NvAPI_Delegate<NvAPI_DRS_DestroySessionDelegate>(NvAPI_DRS_DestroySession_ID);
  61. _initialized = true;
  62. }
  63. }
  64. private static uint MakeVersion<T>(uint version) where T : unmanaged
  65. {
  66. return (uint)Unsafe.SizeOf<T>() | version << 16;
  67. }
  68. public static void SetThreadedOptimization(bool enabled)
  69. {
  70. Initialize();
  71. uint targetValue = (uint)(enabled ? Nvapi.OglThreadControlEnable : Nvapi.OglThreadControlDisable);
  72. Check(NvAPI_Initialize());
  73. Check(NvAPI_DRS_CreateSession(out IntPtr handle));
  74. Check(NvAPI_DRS_LoadSettings(handle));
  75. IntPtr profileHandle;
  76. // Check if the profile already exists.
  77. int status = NvAPI_DRS_FindProfileByName(handle, new NvapiUnicodeString(ProfileName), out profileHandle);
  78. if (status != 0)
  79. {
  80. NvdrsProfile profile = new NvdrsProfile {
  81. Version = MakeVersion<NvdrsProfile>(1),
  82. IsPredefined = 0,
  83. GpuSupport = uint.MaxValue
  84. };
  85. profile.ProfileName.Set(ProfileName);
  86. Check(NvAPI_DRS_CreateProfile(handle, ref profile, out profileHandle));
  87. NvdrsApplicationV4 application = new NvdrsApplicationV4
  88. {
  89. Version = MakeVersion<NvdrsApplicationV4>(4),
  90. IsPredefined = 0,
  91. Flags = 3 // IsMetro, IsCommandLine
  92. };
  93. application.AppName.Set("Ryujinx.exe");
  94. application.UserFriendlyName.Set("Ryujinx");
  95. application.Launcher.Set("");
  96. application.FileInFolder.Set("");
  97. Check(NvAPI_DRS_CreateApplication(handle, profileHandle, ref application));
  98. }
  99. NvdrsSetting setting = new NvdrsSetting
  100. {
  101. Version = MakeVersion<NvdrsSetting>(1),
  102. SettingId = Nvapi.OglThreadControlId,
  103. SettingType = NvdrsSettingType.NvdrsDwordType,
  104. SettingLocation = NvdrsSettingLocation.NvdrsCurrentProfileLocation,
  105. IsCurrentPredefined = 0,
  106. IsPredefinedValid = 0,
  107. CurrentValue = targetValue,
  108. PredefinedValue = targetValue
  109. };
  110. Check(NvAPI_DRS_SetSetting(handle, profileHandle, ref setting));
  111. Check(NvAPI_DRS_SaveSettings(handle));
  112. NvAPI_DRS_DestroySession(handle);
  113. }
  114. private static T NvAPI_Delegate<T>(uint id) where T : class
  115. {
  116. IntPtr ptr = nvapi_QueryInterface(id);
  117. if (ptr != IntPtr.Zero)
  118. {
  119. return Marshal.GetDelegateForFunctionPointer(ptr, typeof(T)) as T;
  120. }
  121. else
  122. {
  123. return null;
  124. }
  125. }
  126. }
  127. }