Forcibly enable threaded optimization on boot.
This commit is contained in:
parent
b1c3e01691
commit
1239c82d2f
8 changed files with 327 additions and 3 deletions
22
Ryujinx.Common/GraphicsDriver/DriverUtilities.cs
Normal file
22
Ryujinx.Common/GraphicsDriver/DriverUtilities.cs
Normal file
|
@ -0,0 +1,22 @@
|
|||
using System;
|
||||
|
||||
namespace Ryujinx.Common.GraphicsDriver
|
||||
{
|
||||
public static class DriverUtilities
|
||||
{
|
||||
public static void ToggleOGLThreading(bool enabled)
|
||||
{
|
||||
Environment.SetEnvironmentVariable("mesa_glthread", enabled.ToString());
|
||||
Environment.SetEnvironmentVariable("__GL_THREADED_OPTIMIZATIONS", enabled ? "1" : "0");
|
||||
|
||||
try
|
||||
{
|
||||
NVThreadedOptimization.SetThreadedOptimization(enabled);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// NVAPI is not available, or couldn't change the application profile.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
Ryujinx.Common/GraphicsDriver/NVAPI/Nvapi.cs
Normal file
11
Ryujinx.Common/GraphicsDriver/NVAPI/Nvapi.cs
Normal file
|
@ -0,0 +1,11 @@
|
|||
namespace Ryujinx.Common.GraphicsDriver.NVAPI
|
||||
{
|
||||
enum Nvapi : uint
|
||||
{
|
||||
OglThreadControlId = 0x20C1221E,
|
||||
|
||||
OglThreadControlDefault = 0,
|
||||
OglThreadControlEnable = 1,
|
||||
OglThreadControlDisable = 2
|
||||
}
|
||||
}
|
42
Ryujinx.Common/GraphicsDriver/NVAPI/NvapiUnicodeString.cs
Normal file
42
Ryujinx.Common/GraphicsDriver/NVAPI/NvapiUnicodeString.cs
Normal file
|
@ -0,0 +1,42 @@
|
|||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Ryujinx.Common.GraphicsDriver.NVAPI
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||
public unsafe struct NvapiUnicodeString
|
||||
{
|
||||
public fixed byte Data[4096];
|
||||
|
||||
public NvapiUnicodeString(string text)
|
||||
{
|
||||
Set(text);
|
||||
}
|
||||
|
||||
public string Get()
|
||||
{
|
||||
fixed (byte* data = Data)
|
||||
{
|
||||
string text = Encoding.Unicode.GetString(data, 4096);
|
||||
|
||||
int index = text.IndexOf('\0');
|
||||
if (index > -1)
|
||||
{
|
||||
text = text.Remove(index);
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
public void Set(string text)
|
||||
{
|
||||
text += '\0';
|
||||
fixed (char* textPtr = text)
|
||||
fixed (byte* data = Data)
|
||||
{
|
||||
int written = Encoding.Unicode.GetBytes(textPtr, text.Length, data, 4096);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
17
Ryujinx.Common/GraphicsDriver/NVAPI/NvdrsApplicationV4.cs
Normal file
17
Ryujinx.Common/GraphicsDriver/NVAPI/NvdrsApplicationV4.cs
Normal file
|
@ -0,0 +1,17 @@
|
|||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Common.GraphicsDriver.NVAPI
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||
unsafe struct NvdrsApplicationV4
|
||||
{
|
||||
public uint Version;
|
||||
public uint IsPredefined;
|
||||
public NvapiUnicodeString AppName;
|
||||
public NvapiUnicodeString UserFriendlyName;
|
||||
public NvapiUnicodeString Launcher;
|
||||
public NvapiUnicodeString FileInFolder;
|
||||
public uint Flags;
|
||||
public NvapiUnicodeString CommandLine;
|
||||
}
|
||||
}
|
16
Ryujinx.Common/GraphicsDriver/NVAPI/NvdrsProfile.cs
Normal file
16
Ryujinx.Common/GraphicsDriver/NVAPI/NvdrsProfile.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Common.GraphicsDriver.NVAPI
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
unsafe struct NvdrsProfile
|
||||
{
|
||||
public uint Version;
|
||||
public NvapiUnicodeString ProfileName;
|
||||
public uint GpuSupport;
|
||||
public uint IsPredefined;
|
||||
public uint NumOfApps;
|
||||
public uint NumOfSettings;
|
||||
}
|
||||
}
|
49
Ryujinx.Common/GraphicsDriver/NVAPI/NvdrsSetting.cs
Normal file
49
Ryujinx.Common/GraphicsDriver/NVAPI/NvdrsSetting.cs
Normal file
|
@ -0,0 +1,49 @@
|
|||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Common.GraphicsDriver.NVAPI
|
||||
{
|
||||
enum NvdrsSettingType : uint
|
||||
{
|
||||
NvdrsDwordType,
|
||||
NvdrsBinaryType,
|
||||
NvdrsStringType,
|
||||
NvdrsWstringType,
|
||||
}
|
||||
|
||||
enum NvdrsSettingLocation : uint
|
||||
{
|
||||
NvdrsCurrentProfileLocation,
|
||||
NvdrsGlobalProfileLocation,
|
||||
NvdrsBaseProfileLocation,
|
||||
NvdrsDefaultProfileLocation,
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Size = 0x3020)]
|
||||
unsafe struct NvdrsSetting
|
||||
{
|
||||
[FieldOffset(0x0)]
|
||||
public uint Version;
|
||||
[FieldOffset(0x4)]
|
||||
public NvapiUnicodeString SettingName;
|
||||
[FieldOffset(0x1004)]
|
||||
public Nvapi SettingId;
|
||||
[FieldOffset(0x1008)]
|
||||
public NvdrsSettingType SettingType;
|
||||
[FieldOffset(0x100C)]
|
||||
public NvdrsSettingLocation SettingLocation;
|
||||
[FieldOffset(0x1010)]
|
||||
public uint IsCurrentPredefined;
|
||||
[FieldOffset(0x1014)]
|
||||
public uint IsPredefinedValid;
|
||||
|
||||
[FieldOffset(0x1018)]
|
||||
public uint PredefinedValue;
|
||||
[FieldOffset(0x1018)]
|
||||
public NvapiUnicodeString PredefinedString;
|
||||
|
||||
[FieldOffset(0x201C)]
|
||||
public uint CurrentValue;
|
||||
[FieldOffset(0x201C)]
|
||||
public NvapiUnicodeString CurrentString;
|
||||
}
|
||||
}
|
163
Ryujinx.Common/GraphicsDriver/NVThreadedOptimization.cs
Normal file
163
Ryujinx.Common/GraphicsDriver/NVThreadedOptimization.cs
Normal file
|
@ -0,0 +1,163 @@
|
|||
using Ryujinx.Common.GraphicsDriver.NVAPI;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Common.GraphicsDriver
|
||||
{
|
||||
static class NVThreadedOptimization
|
||||
{
|
||||
private const string ProfileName = "Ryujinx Nvidia Profile";
|
||||
|
||||
private const uint NvAPI_Initialize_ID = 0x0150E828;
|
||||
private const uint NvAPI_DRS_CreateSession_ID = 0x0694D52E;
|
||||
private const uint NvAPI_DRS_LoadSettings_ID = 0x375DBD6B;
|
||||
private const uint NvAPI_DRS_FindProfileByName_ID = 0x7E4A9A0B;
|
||||
private const uint NvAPI_DRS_CreateProfile_ID = 0x0CC176068;
|
||||
private const uint NvAPI_DRS_CreateApplication_ID = 0x4347A9DE;
|
||||
private const uint NvAPI_DRS_SetSetting_ID = 0x577DD202;
|
||||
private const uint NvAPI_DRS_SaveSettings_ID = 0xFCBC7E14;
|
||||
private const uint NvAPI_DRS_DestroySession_ID = 0x0DAD9CFF8;
|
||||
|
||||
[DllImport("nvapi64")]
|
||||
private static extern IntPtr nvapi_QueryInterface(uint id);
|
||||
|
||||
private delegate int NvAPI_InitializeDelegate();
|
||||
private static NvAPI_InitializeDelegate NvAPI_Initialize;
|
||||
|
||||
private delegate int NvAPI_DRS_CreateSessionDelegate(out long handle);
|
||||
private static NvAPI_DRS_CreateSessionDelegate NvAPI_DRS_CreateSession;
|
||||
|
||||
private delegate int NvAPI_DRS_LoadSettingsDelegate(long handle);
|
||||
private static NvAPI_DRS_LoadSettingsDelegate NvAPI_DRS_LoadSettings;
|
||||
|
||||
private delegate int NvAPI_DRS_FindProfileByNameDelegate(long handle, NvapiUnicodeString profileName, out long profileHandle);
|
||||
private static NvAPI_DRS_FindProfileByNameDelegate NvAPI_DRS_FindProfileByName;
|
||||
|
||||
private delegate int NvAPI_DRS_CreateProfileDelegate(long handle, ref NvdrsProfile profileInfo, out long profileHandle);
|
||||
private static NvAPI_DRS_CreateProfileDelegate NvAPI_DRS_CreateProfile;
|
||||
|
||||
private delegate int NvAPI_DRS_CreateApplicationDelegate(long handle, long profileHandle, ref NvdrsApplicationV4 app);
|
||||
private static NvAPI_DRS_CreateApplicationDelegate NvAPI_DRS_CreateApplication;
|
||||
|
||||
private delegate int NvAPI_DRS_SetSettingDelegate(long handle, long profileHandle, ref NvdrsSetting setting);
|
||||
private static NvAPI_DRS_SetSettingDelegate NvAPI_DRS_SetSetting;
|
||||
|
||||
private delegate int NvAPI_DRS_SaveSettingsDelegate(long handle);
|
||||
private static NvAPI_DRS_SaveSettingsDelegate NvAPI_DRS_SaveSettings;
|
||||
|
||||
private delegate int NvAPI_DRS_DestroySessionDelegate(long handle);
|
||||
private static NvAPI_DRS_DestroySessionDelegate NvAPI_DRS_DestroySession;
|
||||
|
||||
private static bool _initialized;
|
||||
|
||||
private static void Check(int status)
|
||||
{
|
||||
if (status != 0)
|
||||
{
|
||||
throw new Exception($"NVAPI Error: {status}");
|
||||
}
|
||||
}
|
||||
|
||||
private static void Initialize()
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
NvAPI_Initialize = NvAPI_Delegate<NvAPI_InitializeDelegate>(NvAPI_Initialize_ID);
|
||||
|
||||
Check(NvAPI_Initialize());
|
||||
|
||||
NvAPI_DRS_CreateSession = NvAPI_Delegate<NvAPI_DRS_CreateSessionDelegate>(NvAPI_DRS_CreateSession_ID);
|
||||
NvAPI_DRS_LoadSettings = NvAPI_Delegate<NvAPI_DRS_LoadSettingsDelegate>(NvAPI_DRS_LoadSettings_ID);
|
||||
NvAPI_DRS_FindProfileByName = NvAPI_Delegate<NvAPI_DRS_FindProfileByNameDelegate>(NvAPI_DRS_FindProfileByName_ID);
|
||||
NvAPI_DRS_CreateProfile = NvAPI_Delegate<NvAPI_DRS_CreateProfileDelegate>(NvAPI_DRS_CreateProfile_ID);
|
||||
NvAPI_DRS_CreateApplication = NvAPI_Delegate<NvAPI_DRS_CreateApplicationDelegate>(NvAPI_DRS_CreateApplication_ID);
|
||||
NvAPI_DRS_SetSetting = NvAPI_Delegate<NvAPI_DRS_SetSettingDelegate>(NvAPI_DRS_SetSetting_ID);
|
||||
NvAPI_DRS_SaveSettings = NvAPI_Delegate<NvAPI_DRS_SaveSettingsDelegate>(NvAPI_DRS_SaveSettings_ID);
|
||||
NvAPI_DRS_DestroySession = NvAPI_Delegate<NvAPI_DRS_DestroySessionDelegate>(NvAPI_DRS_DestroySession_ID);
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
private static uint MakeVersion<T>(uint version) where T : unmanaged
|
||||
{
|
||||
return (uint)Unsafe.SizeOf<T>() | version << 16;
|
||||
}
|
||||
|
||||
public static unsafe void SetThreadedOptimization(bool enabled)
|
||||
{
|
||||
Initialize();
|
||||
|
||||
uint targetValue = (uint)(enabled ? Nvapi.OglThreadControlEnable : Nvapi.OglThreadControlDisable);
|
||||
|
||||
Check(NvAPI_Initialize());
|
||||
|
||||
Check(NvAPI_DRS_CreateSession(out long handle));
|
||||
|
||||
Check(NvAPI_DRS_LoadSettings(handle));
|
||||
|
||||
long profileHandle;
|
||||
|
||||
// Check if the profile already exists.
|
||||
|
||||
int status = NvAPI_DRS_FindProfileByName(handle, new NvapiUnicodeString(ProfileName), out profileHandle);
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
NvdrsProfile profile = new NvdrsProfile {
|
||||
Version = MakeVersion<NvdrsProfile>(1),
|
||||
IsPredefined = 0,
|
||||
GpuSupport = uint.MaxValue
|
||||
};
|
||||
profile.ProfileName.Set(ProfileName);
|
||||
Check(NvAPI_DRS_CreateProfile(handle, ref profile, out profileHandle));
|
||||
|
||||
NvdrsApplicationV4 application = new NvdrsApplicationV4
|
||||
{
|
||||
Version = MakeVersion<NvdrsApplicationV4>(4),
|
||||
IsPredefined = 0,
|
||||
Flags = 3 // IsMetro, IsCommandLine
|
||||
};
|
||||
application.AppName.Set("Ryujinx.exe");
|
||||
application.UserFriendlyName.Set("Ryujinx");
|
||||
application.Launcher.Set("");
|
||||
application.FileInFolder.Set("");
|
||||
|
||||
Check(NvAPI_DRS_CreateApplication(handle, profileHandle, ref application));
|
||||
}
|
||||
|
||||
NvdrsSetting setting = new NvdrsSetting
|
||||
{
|
||||
Version = MakeVersion<NvdrsSetting>(1),
|
||||
SettingId = Nvapi.OglThreadControlId,
|
||||
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<T>(uint id) where T : class
|
||||
{
|
||||
IntPtr ptr = nvapi_QueryInterface(id);
|
||||
|
||||
if (ptr != IntPtr.Zero)
|
||||
{
|
||||
return Marshal.GetDelegateForFunctionPointer(ptr, typeof(T)) as T;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
using ARMeilleure.Translation.PTC;
|
||||
using Gtk;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.GraphicsDriver;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.System;
|
||||
using Ryujinx.Common.SystemInfo;
|
||||
|
@ -136,6 +137,12 @@ namespace Ryujinx
|
|||
// Logging system information.
|
||||
PrintSystemInfo();
|
||||
|
||||
// Force dedicated GPU if we can.
|
||||
ForceDedicatedGpu.Nvidia();
|
||||
|
||||
// Enable OGL multithreading on the driver, when available.
|
||||
DriverUtilities.ToggleOGLThreading(true);
|
||||
|
||||
// Initialize Gtk.
|
||||
Application.Init();
|
||||
|
||||
|
@ -147,9 +154,6 @@ namespace Ryujinx
|
|||
UserErrorDialog.CreateUserErrorDialog(UserError.NoKeys);
|
||||
}
|
||||
|
||||
// Force dedicated GPU if we can.
|
||||
ForceDedicatedGpu.Nvidia();
|
||||
|
||||
// Show the main window UI.
|
||||
MainWindow mainWindow = new MainWindow();
|
||||
mainWindow.Show();
|
||||
|
|
Reference in a new issue