using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ValheimUpscaler.Recon")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+a10b50c79e0bc65ddd7cab69f8374d7bea781499")] [assembly: AssemblyProduct("ValheimUpscaler.Recon")] [assembly: AssemblyTitle("ValheimUpscaler.Recon")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ValheimUpscaler.Inject { internal static class BuildConfig { public const string Mode = "RELEASE"; public const bool IsDev = false; public const bool DebugOverlay = false; public const bool DevHotkeys = false; public const bool VerboseGpuLogs = false; public const bool InternalResolutionOverride = true; } internal static class Log { internal static ManualLogSource Source; [Conditional("BUILD_DEV")] public static void Trace(string msg) { } [Conditional("BUILD_DEV")] public static void Debug(string msg) { } public static void Info(string msg) { ManualLogSource source = Source; if (source != null) { source.LogInfo((object)msg); } } public static void Warning(string msg) { ManualLogSource source = Source; if (source != null) { source.LogWarning((object)msg); } } public static void Error(string msg) { ManualLogSource source = Source; if (source != null) { source.LogError((object)msg); } } } internal static class HotkeyRegistry { internal readonly struct Hotkey { public readonly KeyCode Key; public readonly string Description; public readonly Action Action; public Hotkey(KeyCode key, string description, Action action) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) Key = key; Description = description; Action = action; } } private static readonly List _hotkeys = new List(); public static IReadOnlyList All => _hotkeys; public static void Register(KeyCode key, string description, Action action) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < _hotkeys.Count; i++) { if (_hotkeys[i].Key == key) { Log.Warning($"Hotkey {key} registered twice; keeping the first ('{_hotkeys[i].Description}')."); return; } } _hotkeys.Add(new Hotkey(key, description, action)); } public static void ProcessInput() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < _hotkeys.Count; i++) { if (Input.GetKeyDown(_hotkeys[i].Key)) { try { _hotkeys[i].Action(); } catch (Exception arg) { Log.Error($"Hotkey {_hotkeys[i].Key} handler failed: {arg}"); } } } } } public class ReflexPacer : MonoBehaviour { private void Update() { UpscalerRunner.CurrentFrameId = (ulong)Time.frameCount; UpscalerNative.EmitLatencyMarker(0, UpscalerRunner.CurrentFrameId); } private void LateUpdate() { UpscalerNative.EmitLatencyMarker(1, UpscalerRunner.CurrentFrameId); } } public class MipmapBiasManager : MonoBehaviour { private float _lastBias; private float _checkTimer; private void Update() { _checkTimer -= Time.deltaTime; if (!(_checkTimer > 0f)) { _checkTimer = 5f; float num = Patches.CurrentQualityScale(); float num2 = ((num < 1f) ? Mathf.Log(num, 2f) : 0f); if (num2 != 0f || _lastBias != 0f) { _lastBias = num2; ApplyBias(num2); } } } private void ApplyBias(float bias) { Texture2D[] array = Resources.FindObjectsOfTypeAll(); foreach (Texture2D val in array) { if ((Object)(object)val != (Object)null && ((Texture)val).mipMapBias != bias) { ((Texture)val).mipMapBias = bias; } } } } public enum DlssQuality { Native, Quality, Balanced, Performance, UltraPerformance, Custom } public enum UpscalerBackend { Auto, DLSS, FSR31, XeSS } [BepInPlugin("dev.daniel.valheim.upscaler.inject", "Valheim Upscaler Injection", "0.3.1")] [BepInProcess("valheim.exe")] public class InjectPlugin : BaseUnityPlugin { public const string GUID = "dev.daniel.valheim.upscaler.inject"; public const string NAME = "Valheim Upscaler Injection"; public const string VERSION = "0.3.1"; public static ConfigEntry ConfigEnableDLSS; public static ConfigEntry ConfigEnableFG; public static ConfigEntry ConfigBackend; public static ConfigEntry ConfigDLSSMode; public static ConfigEntry ConfigCustomScale; public static ConfigEntry ConfigCustomResolutionPreset; private static bool _showMenu; private Rect _windowRect = new Rect(20f, 20f, 300f, 250f); private float _fgStatusPolledAt = -999f; private int _fgStatusCached = -1; private bool _fgSubmittingCached; public static bool IsMenuOpen() { return _showMenu; } private void ToggleMenu() { SetMenuOpen(!_showMenu); } private void SetMenuOpen(bool open) { if (_showMenu == open) { return; } _showMenu = open; if (_showMenu) { Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; return; } bool flag = false; try { Type type = AccessTools.TypeByName("Menu"); if (type != null) { MethodInfo methodInfo = AccessTools.Method(type, "IsVisible", (Type[])null, (Type[])null); if (methodInfo != null) { flag |= (bool)methodInfo.Invoke(null, null); } } Type type2 = AccessTools.TypeByName("InventoryGui"); if (type2 != null) { FieldInfo fieldInfo = AccessTools.Field(type2, "m_instance"); if (fieldInfo != null) { object value = fieldInfo.GetValue(null); if (value != null) { MethodInfo methodInfo2 = AccessTools.Method(type2, "IsVisible", (Type[])null, (Type[])null); if (methodInfo2 != null) { flag |= (bool)methodInfo2.Invoke(value, null); } } } } } catch (Exception ex) { Log.Warning("Error checking other menus: " + ex.Message); } if (!flag) { Cursor.lockState = (CursorLockMode)1; Cursor.visible = false; } } private void Awake() { //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Invalid comparison between Unknown and I4 //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Invalid comparison between Unknown and I4 //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Expected O, but got Unknown //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Expected O, but got Unknown //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Expected O, but got Unknown //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Expected O, but got Unknown //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Expected O, but got Unknown //IL_03b7: Unknown result type (might be due to invalid IL or missing references) //IL_03c5: Expected O, but got Unknown ConfigEnableDLSS = ((BaseUnityPlugin)this).Config.Bind("Upscaler", "Enable DLSS", true, "Enable DLSS/FSR upscaling"); ConfigEnableFG = ((BaseUnityPlugin)this).Config.Bind("Upscaler", "Enable Frame Generation", false, "Experimental DLSS-G frame generation (direct NGX, NVIDIA only). Off by default - also needs OptiScaler's [FrameGen] Enabled=true and FGInput=dlssg/nukems set (Insert overlay or OptiScaler.ini)."); ConfigBackend = ((BaseUnityPlugin)this).Config.Bind("Upscaler", "Preferred Upscaler", UpscalerBackend.Auto, "Which technology OptiScaler should output. Auto picks by GPU vendor (NVIDIA=DLSS, AMD=FSR 3.1, Intel=XeSS). Written to OptiScaler.ini; a change applies on the NEXT game launch."); ConfigDLSSMode = ((BaseUnityPlugin)this).Config.Bind("Upscaler", "Quality Mode", DlssQuality.Quality, "Resolution preset"); ConfigCustomScale = ((BaseUnityPlugin)this).Config.Bind("Upscaler", "Custom Scale", 0.67f, new ConfigDescription("Custom render scale (0.1 - 1.0)", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 1f), Array.Empty())); ConfigCustomResolutionPreset = ((BaseUnityPlugin)this).Config.Bind("Upscaler", "Custom Resolution Preset", false, "When enabled, the mod controls the game's internal rendering resolution (legacy mode). When disabled (default), the game's own resolution settings remain authoritative."); Log.Source = ((BaseUnityPlugin)this).Logger; Log.Info(string.Format("{0} {1} awake ({2} build). graphicsDeviceType={3}", "Valheim Upscaler Injection", "0.3.1", "RELEASE", SystemInfo.graphicsDeviceType)); RegisterHotkeys(); BackendSelector.Apply(); if ((int)SystemInfo.graphicsDeviceType != 18 && (int)SystemInfo.graphicsDeviceType != 21) { Log.Warning("Not running under Direct3D12 or Vulkan - launch Valheim with -force-d3d12 (or -force-vulkan), or the native upscaler can't work."); } try { Type type = AccessTools.TypeByName("FrameBufferScaler"); if (type == null) { Log.Error("FrameBufferScaler type NOT found - wrong game/version? Aborting patches."); return; } MethodInfo methodInfo = AccessTools.Method(type, "OnBufferCreated", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(type, "OnBufferDestroyed", (Type[])null, (Type[])null); if (methodInfo == null || methodInfo2 == null) { Log.Error($"Method lookup failed (OnBufferCreated={methodInfo != null}, OnBufferDestroyed={methodInfo2 != null}). " + "Valheim may have renamed them - re-run ReconPlugin to get current names."); return; } Harmony val = new Harmony("dev.daniel.valheim.upscaler.inject"); val.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(Patches), "Created", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(Patches), "Destroyed", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); MethodInfo methodInfo3 = AccessTools.Method(AccessTools.TypeByName("UpscaledFrameBuffer"), "UpdateCurrentRenderScale", (Type[])null, (Type[])null) ?? AccessTools.Method(type, "UpdateCurrentRenderScale", (Type[])null, (Type[])null); if (methodInfo3 != null) { val.Patch((MethodBase)methodInfo3, new HarmonyMethod(AccessTools.Method(typeof(Patches), "UpdateCurrentRenderScalePrefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else { Log.Warning("UpdateCurrentRenderScale NOT found on UpscaledFrameBuffer or FrameBufferScaler - quality modes won't drive render scale (game slider stays in control). Re-run ReconPlugin."); } Type type2 = AccessTools.TypeByName("Menu"); if (type2 != null) { MethodInfo methodInfo4 = AccessTools.Method(type2, "IsVisible", (Type[])null, (Type[])null); if (methodInfo4 != null) { val.Patch((MethodBase)methodInfo4, new HarmonyMethod(AccessTools.Method(typeof(Patches), "MenuIsVisiblePrefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else { Log.Warning("Menu.IsVisible method NOT found!"); } } else { Log.Warning("Menu type NOT found!"); } MethodInfo methodInfo5 = AccessTools.Method(typeof(Graphics), "DrawMeshInstanced", new Type[9] { typeof(Mesh), typeof(int), typeof(Material), typeof(Matrix4x4[]), typeof(int), typeof(MaterialPropertyBlock), typeof(ShadowCastingMode), typeof(bool), typeof(int) }, (Type[])null); if (methodInfo5 != null) { val.Patch((MethodBase)methodInfo5, new HarmonyMethod(AccessTools.Method(typeof(Patches), "DrawMeshInstancedPrefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else { Log.Warning("Graphics.DrawMeshInstanced method NOT found!"); } Log.Info("Harmony patches applied to FrameBufferScaler.OnBufferCreated/OnBufferDestroyed. Lower render scale below 100% in-world to trigger OnBufferCreated."); } catch (Exception ex) { Log.Error("Harmony patch FAILED: " + ex); } UpscalerRunner.Init(); } private void RegisterHotkeys() { HotkeyRegistry.Register((KeyCode)284, "Toggle the Upscaler Menu", ToggleMenu); HotkeyRegistry.Register((KeyCode)288, "Toggle upscaling (A/B vs vanilla)", InjectState.ToggleDisplay); HotkeyRegistry.Register((KeyCode)292, "Toggle DLSS-G frame generation (experimental)", ToggleFrameGeneration); HotkeyRegistry.Register((KeyCode)283, "Toggle the Upscaler Menu (custom resolution preset only)", delegate { if (ConfigCustomResolutionPreset.Value) { ToggleMenu(); } }); } private void ToggleFrameGeneration() { if (GpuInfo.Vendor != GpuVendor.Nvidia) { Log.Info($"Frame Generation (DLSS-G) unavailable: NVIDIA-only feature (GPU vendor: {GpuInfo.Vendor}). " + "OptiScaler's own FG (OptiFG) remains available via its Insert overlay."); return; } ConfigEnableFG.Value = !ConfigEnableFG.Value; Log.Info("Frame Generation (DLSS-G) " + (ConfigEnableFG.Value ? "ON" : "OFF") + " (experimental; also needs OptiScaler's FrameGen Enabled + FGInput=dlssg/nukems)"); } private void Update() { HotkeyRegistry.ProcessInput(); if (_showMenu) { Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; } } private void OnGUI() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) if (_showMenu) { float num = Mathf.Max(1f, (float)Screen.height / 1080f); GUI.matrix = Matrix4x4.Scale(new Vector3(num, num, 1f)); _windowRect = GUILayout.Window(98765, _windowRect, new WindowFunction(DrawMenu), "Upscaler Menu", Array.Empty()); } } private void DrawMenu(int windowID) { //IL_042e: Unknown result type (might be due to invalid IL or missing references) bool flag = GUILayout.Toggle(ConfigEnableDLSS.Value, "Enable Upscaling (F7)", Array.Empty()); if (flag != ConfigEnableDLSS.Value) { ConfigEnableDLSS.Value = flag; InjectState.SetDisplay(InjectState.Enabled ? InjectState.Output : InjectState.LowResInput); Log.Info("Injection " + (InjectState.Enabled ? "ON" : "OFF (vanilla)")); } bool flag2 = GUILayout.Toggle(ConfigCustomResolutionPreset.Value, "Custom Resolution Preset (Legacy Mode)", Array.Empty()); if (flag2 != ConfigCustomResolutionPreset.Value) { ConfigCustomResolutionPreset.Value = flag2; } GUILayout.Space(10f); GUILayout.Label($"GPU: {GpuInfo.Vendor} Backend: {BackendSelector.SelectedBackend}", Array.Empty()); GUILayout.Label("Preferred Upscaler (applies next launch):", Array.Empty()); foreach (UpscalerBackend value in Enum.GetValues(typeof(UpscalerBackend))) { if (GUILayout.Toggle(ConfigBackend.Value == value, value.ToString(), Array.Empty()) && ConfigBackend.Value != value) { ConfigBackend.Value = value; BackendSelector.Apply(); } } GUILayout.Space(10f); if (ConfigCustomResolutionPreset.Value) { GUILayout.Label("Quality Mode (Legacy Mode):", Array.Empty()); foreach (DlssQuality value2 in Enum.GetValues(typeof(DlssQuality))) { if (GUILayout.Toggle(ConfigDLSSMode.Value == value2, value2.ToString(), Array.Empty()) && ConfigDLSSMode.Value != value2) { ConfigDLSSMode.Value = value2; } } if (ConfigDLSSMode.Value == DlssQuality.Custom) { GUILayout.Space(10f); GUILayout.Label($"Custom Scale: {ConfigCustomScale.Value:F2}", Array.Empty()); float num = GUILayout.HorizontalSlider(ConfigCustomScale.Value, 0.1f, 1f, Array.Empty()); if (Mathf.Abs(num - ConfigCustomScale.Value) > 0.01f) { ConfigCustomScale.Value = num; } } } else { GUILayout.Label("Quality Mode: (Controlled by Game Resolution/Slider)", Array.Empty()); } GUILayout.Space(10f); if (GpuInfo.Vendor == GpuVendor.Nvidia) { bool flag3 = GUILayout.Toggle(ConfigEnableFG.Value, "Enable Frame Generation (F11)", Array.Empty()); if (flag3 != ConfigEnableFG.Value) { ConfigEnableFG.Value = flag3; Log.Info("Frame Generation (DLSS-G) " + (ConfigEnableFG.Value ? "ON" : "OFF") + " (experimental; also needs OptiScaler's FrameGen Enabled + FGInput=dlssg/nukems)"); } if (Time.unscaledTime - _fgStatusPolledAt > 1f) { _fgStatusPolledAt = Time.unscaledTime; _fgStatusCached = UpscalerNative.DlssGStatus(); _fgSubmittingCached = UpscalerNative.IsFgWritingOutput(); } string text = ((_fgStatusCached == 0) ? "NVIDIA DLSS-G (Native)" : ((_fgStatusCached == -1) ? "OptiScaler / Custom" : $"Error (Status: {_fgStatusCached})")); GUILayout.Label("Current FG Backend: " + text, Array.Empty()); GUILayout.Label($"FG status: avail={UpscalerNative.FgAvailable} submitting={_fgSubmittingCached}", Array.Empty()); GUILayout.Label("Needs OptiScaler's FrameGen Enabled + FGInput=dlssg/nukems (Insert overlay).", Array.Empty()); } else { GUILayout.Label($"Frame Generation: unavailable on {GpuInfo.Vendor} GPUs (DLSS-G is NVIDIA-only).", Array.Empty()); GUILayout.Label("OptiScaler's own FG (OptiFG) is available via its Insert overlay.", Array.Empty()); } GUILayout.Space(10f); GUILayout.Label("Hotkeys:", Array.Empty()); IReadOnlyList all = HotkeyRegistry.All; for (int i = 0; i < all.Count; i++) { GUILayout.Label($" {all[i].Key}: {all[i].Description}", Array.Empty()); } GUI.DragWindow(); } private void OnDestroy() { UpscalerRunner.Dispose(); } } internal static class Diag { [Conditional("BUILD_DEV")] public static void Eval(string status) { } [Conditional("FEATURE_ENABLE_DEBUG_OVERLAY")] public static void Heartbeat() { } [Conditional("FEATURE_ENABLE_DEBUG_OVERLAY")] public static void DumpStatus() { } } internal static class BackendSelector { public static bool OptiScalerPresent { get; private set; } public static string SelectedBackend { get; private set; } = "(not applied)"; private static string GameDir => Path.GetDirectoryName(Application.dataPath); public static void Apply() { GpuInfo.Detect(); string gameDir = GameDir; OptiScalerPresent = File.Exists(Path.Combine(gameDir, "OptiScaler.ini")) || File.Exists(Path.Combine(gameDir, "OptiScaler.dll")) || File.Exists(Path.Combine(gameDir, "dxgi.dll")) || File.Exists(Path.Combine(gameDir, "winmm.dll")) || File.Exists(Path.Combine(gameDir, "version.dll")) || File.Exists(Path.Combine(gameDir, "nvngx.dll")); UpscalerBackend upscalerBackend = InjectPlugin.ConfigBackend?.Value ?? UpscalerBackend.Auto; UpscalerBackend upscalerBackend2 = upscalerBackend; if (upscalerBackend == UpscalerBackend.Auto) { upscalerBackend2 = GpuInfo.Vendor switch { GpuVendor.Nvidia => UpscalerBackend.DLSS, GpuVendor.Amd => UpscalerBackend.FSR31, GpuVendor.Intel => UpscalerBackend.XeSS, _ => (!OptiScalerPresent) ? UpscalerBackend.DLSS : UpscalerBackend.FSR31, }; } Log.Info($"GPU: {GpuInfo.Vendor} (PCI 0x{GpuInfo.VendorId:X4}) '{SystemInfo.graphicsDeviceName}'. " + string.Format("Backend: {0}{1}; ", upscalerBackend2, (upscalerBackend == UpscalerBackend.Auto) ? " (auto)" : " (user override)") + "OptiScaler " + (OptiScalerPresent ? "present" : "absent") + "."); if (GpuInfo.Vendor != GpuVendor.Nvidia && !OptiScalerPresent) { SelectedBackend = "none (bilinear)"; UpscalerRunner.NativeEvalEnabled = false; Log.Warning("Non-NVIDIA GPU without OptiScaler: no upscaler backend can run. Install OptiScaler (as dxgi.dll next to valheim.exe) to get " + ((GpuInfo.Vendor == GpuVendor.Intel) ? "XeSS" : "FSR") + "; staying on bilinear scaling."); } else if (!OptiScalerPresent) { SelectedBackend = "DLSS (driver NGX)"; } else { string value = (SelectedBackend = upscalerBackend2 switch { UpscalerBackend.XeSS => "xess", UpscalerBackend.DLSS => "dlss", _ => "fsr31", }); TryWriteOptiScalerIni(gameDir, value); } } private static void TryWriteOptiScalerIni(string dir, string value) { try { string path = Path.Combine(dir, "OptiScaler.ini"); object obj = (File.Exists(path) ? ((object)File.ReadAllLines(path)) : ((object)new string[0])); List list = new List(((Array)obj).Length + 2); bool flag = false; bool flag2 = false; bool flag3 = false; int num = -1; string[] array = (string[])obj; for (int i = 0; i < array.Length; i++) { string item; string text = (item = array[i]).Trim(); if (text.StartsWith("[")) { flag = text.Equals("[Upscalers]", StringComparison.OrdinalIgnoreCase); if (flag && num < 0) { num = list.Count; } } else if (flag && !flag2) { int num2 = text.IndexOf('='); if (num2 > 0 && text.Substring(0, num2).Trim().Equals("Dx12Upscaler", StringComparison.OrdinalIgnoreCase)) { flag2 = true; if (!text.Substring(num2 + 1).Trim().Equals(value, StringComparison.OrdinalIgnoreCase)) { flag3 = true; item = "Dx12Upscaler=" + value; } } } list.Add(item); } if (!flag2) { flag3 = true; if (num >= 0) { list.Insert(num + 1, "Dx12Upscaler=" + value); } else { list.Add("[Upscalers]"); list.Add("Dx12Upscaler=" + value); } } if (flag3) { File.WriteAllLines(path, list.ToArray()); Log.Info("OptiScaler.ini updated: Dx12Upscaler=" + value + " (applies on the next launch)."); } } catch (Exception ex) { Log.Warning("Could not update OptiScaler.ini (set Dx12Upscaler manually or via the Insert overlay): " + ex.Message); } } } internal static class Patches { private static IResolutionManager _lastManager; private static bool _isDrawingMask; public static void Created(object __instance, RenderTexture texture) { try { InjectState.OnBufferCreated(__instance, texture); } catch (Exception ex) { Log.Error("OnBufferCreated hook error: " + ex); } } public static void Destroyed() { try { InjectState.OnBufferDestroyed(); } catch (Exception ex) { Log.Error("OnBufferDestroyed hook error: " + ex); } } internal static float CurrentQualityScale() { return ResolutionManagerProvider.Current.GetQualityScale(); } public static bool UpdateCurrentRenderScalePrefix(object __instance) { IResolutionManager current = ResolutionManagerProvider.Current; if (_lastManager != null && _lastManager != current && _lastManager is F2ControlledResolutionManager f2ControlledResolutionManager) { f2ControlledResolutionManager.Restore(__instance); } _lastManager = current; return current.UpdateRenderScale(__instance); } public static bool MenuIsVisiblePrefix(ref bool __result) { if (InjectPlugin.IsMenuOpen()) { __result = true; return false; } return true; } public static void DrawMeshInstancedPrefix(Mesh mesh, int submeshIndex, Material material, Matrix4x4[] matrices, int count, MaterialPropertyBlock properties, ShadowCastingMode castShadows, bool receiveShadows, int layer) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) if (_isDrawingMask || !InjectState.Enabled || !UpscalerRunner.NativeEvalEnabled || !UpscalerNative.Available || !((Object)(object)InjectState.MaskCamera != (Object)null) || !((Object)(object)InjectState.MaskMaterial != (Object)null) || layer != InjectState.GrassLayer || InjectState.GrassLayer < 0) { return; } _isDrawingMask = true; try { Graphics.DrawMeshInstanced(mesh, submeshIndex, InjectState.MaskMaterial, matrices, count, properties, castShadows, receiveShadows, layer, InjectState.MaskCamera); } catch (Exception) { } finally { _isDrawingMask = false; } } } internal static class InjectState { public static bool FlipOutput = false; internal static bool ForceResetSubmit = false; internal static RenderTexture LowResInput; internal static RenderTexture Output; public static RenderTexture ReactiveMask; public static RenderTexture FgInterpOutput; public static Camera MaskCamera; public static Material MaskMaterial; public static int GrassLayer = -1; private static bool _disabledAA; private static object _aaModel; private static bool _originalAAEnabled; private static object _rawImage; private static PropertyInfo _texProp; private static PropertyInfo _uvRectProp; private static bool _flipped; private static UpscaleDispatch _dispatch; private static bool _warnedNoMaskShader; public static bool Enabled => InjectPlugin.ConfigEnableDLSS?.Value ?? true; public static void OnBufferCreated(object frameBufferScaler, RenderTexture lowRes) { //IL_0126: Unknown result type (might be due to invalid IL or missing references) LowResInput = lowRes; ForceResetSubmit = true; UpscalerRunner.InvalidateTextureCache(); _rawImage = AccessTools.Field(frameBufferScaler.GetType(), "m_rawImage")?.GetValue(frameBufferScaler); if (_rawImage == null) { Log.Warning("m_rawImage is NULL on FrameBufferScaler; cannot redirect display."); return; } if (_texProp == null) { _texProp = AccessTools.Property(_rawImage.GetType(), "texture"); } if (_texProp == null) { Log.Warning("RawImage.texture property not found; cannot redirect display."); return; } if (_uvRectProp == null) { _uvRectProp = AccessTools.Property(_rawImage.GetType(), "uvRect"); } EnsureOutput(); EnsureReactiveMask(((Texture)lowRes).width, ((Texture)lowRes).height); EnsureMaskMaterial(); GrassLayer = LayerMask.NameToLayer("InstanceRenderer"); AttachDispatch(lowRes); SetDisplay(Enabled ? Output : LowResInput); DisableConflictingAA(ResolveMainCamera(lowRes)); Log.Info($"OnBufferCreated: lowRes {((Texture)lowRes).width}x{((Texture)lowRes).height} {lowRes.format} -> output {((Texture)Output).width}x{((Texture)Output).height}; " + $"RawImage redirected (enabled={Enabled}). Dispatch attached={(Object)(object)_dispatch != (Object)null}."); } public static void OnBufferDestroyed() { RestoreConflictingAA(); SetOutputFlip(flip: false); if ((Object)(object)LowResInput != (Object)null) { SetDisplay(LowResInput); } UpscalerRunner.InvalidateTextureCache(); ReleaseOutput(); ReleaseReactiveMask(); ReleaseFgInterpOutput(); if ((Object)(object)MaskCamera != (Object)null) { Object.Destroy((Object)(object)((Component)MaskCamera).gameObject); MaskCamera = null; } if ((Object)(object)_dispatch != (Object)null) { Object.DestroyImmediate((Object)(object)_dispatch); _dispatch = null; } LowResInput = null; Log.Info("OnBufferDestroyed: restored vanilla RawImage texture, released output and reactive mask resources."); } private static void EnsureOutput() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown int width = Screen.width; int height = Screen.height; if (!((Object)(object)Output != (Object)null) || ((Texture)Output).width != width || ((Texture)Output).height != height) { ReleaseOutput(); Output = new RenderTexture(width, height, 0, (RenderTextureFormat)2, (RenderTextureReadWrite)1) { name = "Upscaler_Output", filterMode = (FilterMode)1, enableRandomWrite = true }; if (!Output.Create()) { Log.Error("Output RenderTexture.Create() FAILED (UAV ARGBHalf unsupported?)."); } Graphics.Blit((Texture)(object)Texture2D.blackTexture, Output); UpscalerRunner.InvalidateTextureCache(); } } public static void EnsureFgInterpOutput() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown int width = Screen.width; int height = Screen.height; if (!((Object)(object)FgInterpOutput != (Object)null) || ((Texture)FgInterpOutput).width != width || ((Texture)FgInterpOutput).height != height) { ReleaseFgInterpOutput(); FgInterpOutput = new RenderTexture(width, height, 0, (RenderTextureFormat)2, (RenderTextureReadWrite)1) { name = "Upscaler_FgInterpOutput", enableRandomWrite = true }; if (!FgInterpOutput.Create()) { Log.Error("FgInterpOutput RenderTexture.Create() FAILED (UAV ARGBHalf unsupported?)."); } Graphics.Blit((Texture)(object)Texture2D.blackTexture, FgInterpOutput); UpscalerRunner.InvalidateTextureCache(); } } private static void ReleaseFgInterpOutput() { if (!((Object)(object)FgInterpOutput == (Object)null)) { FgInterpOutput.Release(); Object.Destroy((Object)(object)FgInterpOutput); FgInterpOutput = null; } } public static void EnsureReactiveMask(int w, int h) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown if (!((Object)(object)ReactiveMask != (Object)null) || ((Texture)ReactiveMask).width != w || ((Texture)ReactiveMask).height != h) { ReleaseReactiveMask(); ReactiveMask = new RenderTexture(w, h, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)1) { name = "Upscaler_ReactiveMask", filterMode = (FilterMode)1 }; if (!ReactiveMask.Create()) { Log.Error("ReactiveMask RenderTexture.Create() FAILED."); } UpscalerRunner.InvalidateTextureCache(); } } private static void ReleaseReactiveMask() { if (!((Object)(object)ReactiveMask == (Object)null)) { ReactiveMask.Release(); Object.Destroy((Object)(object)ReactiveMask); ReactiveMask = null; } } private static void EnsureMaskMaterial() { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)MaskMaterial != (Object)null) { return; } string[] array = new string[4] { "Unlit/Color", "Sprites/Default", "UI/Default", "Hidden/Internal-Colored" }; for (int i = 0; i < array.Length; i++) { Shader val = Shader.Find(array[i]); if (!((Object)(object)val == (Object)null)) { MaskMaterial = new Material(val); MaskMaterial.enableInstancing = true; MaskMaterial.color = Color.white; return; } } if (!_warnedNoMaskShader) { _warnedNoMaskShader = true; Log.Warning("No usable mask shader in this build; reactive mask disabled (upscaling unaffected)."); } } internal static void DisableConflictingAA(Camera cam) { if (_disabledAA || (Object)(object)cam == (Object)null) { return; } try { Type type = AccessTools.TypeByName("PostProcessingBehaviour"); if (type == null) { return; } Component component = ((Component)cam).GetComponent(type); if ((Object)(object)component == (Object)null) { return; } object obj = AccessTools.Field(type, "profile")?.GetValue(component); if (obj == null) { return; } _aaModel = AccessTools.Field(obj.GetType(), "antialiasing")?.GetValue(obj); if (_aaModel == null) { return; } FieldInfo fieldInfo = AccessTools.Field(_aaModel.GetType(), "m_Enabled") ?? AccessTools.Field(_aaModel.GetType(), "enabled"); if (fieldInfo != null && fieldInfo.FieldType == typeof(bool)) { _originalAAEnabled = (bool)fieldInfo.GetValue(_aaModel); if (_originalAAEnabled) { fieldInfo.SetValue(_aaModel, false); _disabledAA = true; Log.Info("Disabled PPv1 antialiasing (TAA/FXAA). DLSS provides temporal AA — double accumulation and pre-blurring eliminated."); } } } catch (Exception ex) { Log.Warning("Failed to disable conflicting AA: " + ex.Message); } } internal static void RestoreConflictingAA() { if (!_disabledAA || _aaModel == null) { return; } try { (AccessTools.Field(_aaModel.GetType(), "m_Enabled") ?? AccessTools.Field(_aaModel.GetType(), "enabled"))?.SetValue(_aaModel, _originalAAEnabled); _disabledAA = false; Log.Info("Restored PPv1 antialiasing (was " + (_originalAAEnabled ? "enabled" : "disabled") + ")."); } catch (Exception ex) { Log.Warning("Failed to restore AA: " + ex.Message); } } private static void ReleaseOutput() { if (!((Object)(object)Output == (Object)null)) { Output.Release(); Object.Destroy((Object)(object)Output); Output = null; } } private static void AttachDispatch(RenderTexture lowRes) { Camera val = ResolveMainCamera(lowRes); if ((Object)(object)val == (Object)null) { Log.Warning("Main camera NOT found (no camera targets the low-res RT, GameCamera null). Dispatch not attached."); return; } UpscaleDispatch component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null) { Object.DestroyImmediate((Object)(object)component); } _dispatch = ((Component)val).gameObject.AddComponent(); if ((Object)(object)((Component)val).GetComponent() == (Object)null) { ((Component)val).gameObject.AddComponent(); } if ((Object)(object)((Component)val).GetComponent() == (Object)null) { ((Component)val).gameObject.AddComponent(); } Type type = AccessTools.TypeByName("PostProcessingBehaviour"); if (type != null) { Component component2 = ((Component)val).GetComponent(type); _ = (Object)(object)((component2 is MonoBehaviour) ? component2 : null) != (Object)null; } EnsureMaskCamera(val); } private static void EnsureMaskCamera(Camera mainCam) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)MaskCamera != (Object)null)) { GameObject val = new GameObject("Upscaler_MaskCamera"); val.transform.SetParent(((Component)mainCam).transform, false); MaskCamera = val.AddComponent(); ((Behaviour)MaskCamera).enabled = false; if ((Object)(object)ReactiveMask != (Object)null && (Object)(object)LowResInput != (Object)null) { MaskCamera.SetTargetBuffers(ReactiveMask.colorBuffer, LowResInput.depthBuffer); } else { MaskCamera.targetTexture = ReactiveMask; } MaskCamera.cullingMask = ((GrassLayer >= 0) ? (1 << GrassLayer) : 0); } } private static Camera ResolveMainCamera(RenderTexture lowRes) { Camera[] allCameras = Camera.allCameras; foreach (Camera val in allCameras) { if ((Object)(object)val != (Object)null && (Object)(object)val.targetTexture == (Object)(object)lowRes) { return val; } } Type type = AccessTools.TypeByName("GameCamera"); if (type != null) { object obj = AccessTools.Field(type, "m_instance")?.GetValue(null) ?? AccessTools.Property(type, "instance")?.GetValue(null); if (obj != null) { object? obj2 = AccessTools.Field(type, "m_camera")?.GetValue(obj); Camera val2 = (Camera)((obj2 is Camera) ? obj2 : null); if (val2 != null) { return val2; } } } return Camera.main; } internal static void SetDisplay(RenderTexture tex) { if (_rawImage != null && _texProp != null) { _texProp.SetValue(_rawImage, tex, null); } } internal static void SetOutputFlip(bool flip) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) if (_rawImage != null && !(_uvRectProp == null) && flip != _flipped) { _flipped = flip; _uvRectProp.SetValue(_rawImage, (object)(flip ? new Rect(0f, 1f, 1f, -1f) : new Rect(0f, 0f, 1f, 1f)), null); } } internal static void ToggleDisplay() { if (InjectPlugin.ConfigEnableDLSS != null) { InjectPlugin.ConfigEnableDLSS.Value = !InjectPlugin.ConfigEnableDLSS.Value; } SetDisplay(Enabled ? Output : LowResInput); Log.Info("Injection " + (Enabled ? "ON" : "OFF (vanilla)")); } } public class UpscaleDispatch : MonoBehaviour { private Camera _cam; private Matrix4x4 _baseProj; private bool _jittered; private bool _loggedOnce; private bool _depthModeForced; private DepthTextureMode _depthModeBeforeForce; private void Awake() { _cam = ((Component)this).GetComponent(); } private void OnPreCull() { _jittered = false; bool upscalerDepthMode = InjectState.Enabled && (Object)(object)InjectState.LowResInput != (Object)null && UpscalerRunner.ForceMotionVectors; SetUpscalerDepthMode(upscalerDepthMode); if (InjectState.Enabled && !((Object)(object)InjectState.LowResInput == (Object)null)) { UpscalerRunner.ApplyJitter(_cam, ((Texture)InjectState.LowResInput).width, ((Texture)InjectState.LowResInput).height, ref _baseProj, ref _jittered); } } private void OnPostRender() { if (_jittered) { _cam.ResetProjectionMatrix(); _jittered = false; } } private void OnDisable() { SetUpscalerDepthMode(enabled: false); if (_jittered && (Object)(object)_cam != (Object)null) { _cam.ResetProjectionMatrix(); _jittered = false; } } private void SetUpscalerDepthMode(bool enabled) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_cam == (Object)null) { return; } if (enabled) { if (!_depthModeForced) { _depthModeBeforeForce = _cam.depthTextureMode; _depthModeForced = true; } _cam.depthTextureMode = (DepthTextureMode)(_depthModeBeforeForce | 5); } else if (_depthModeForced) { DepthTextureMode val = _cam.depthTextureMode; if ((_depthModeBeforeForce & 1) == 0) { val = (DepthTextureMode)(val & -2); } if ((_depthModeBeforeForce & 4) == 0) { val = (DepthTextureMode)(val & -5); } _cam.depthTextureMode = (DepthTextureMode)(val | (_depthModeBeforeForce & 5)); _depthModeForced = false; } } private void OnRenderImage(RenderTexture src, RenderTexture dst) { //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) if (!_loggedOnce) { _loggedOnce = true; Shader.GetGlobalTexture("_CameraDepthTexture"); Shader.GetGlobalTexture("_CameraMotionVectorsTexture"); } if (!InjectState.Enabled) { InjectState.SetOutputFlip(flip: false); Graphics.Blit((Texture)(object)src, dst); return; } bool flag = !InjectState.ForceResetSubmit && UpscalerRunner.NativeEvalEnabled && UpscalerNative.IsWritingOutput(); bool num = UpscalerRunner.NativeEvalEnabled && UpscalerNative.Available; if ((Object)(object)InjectState.Output != (Object)null && !flag) { Graphics.Blit((Texture)(object)src, InjectState.Output); } if (UpscalerRunner.FgEnabled && (Object)(object)InjectState.FgInterpOutput == (Object)null) { InjectState.EnsureFgInterpOutput(); } if (num && (Object)(object)InjectState.MaskCamera != (Object)null && (Object)(object)InjectState.ReactiveMask != (Object)null && (Object)(object)InjectState.LowResInput != (Object)null && InjectState.GrassLayer >= 0 && (Object)(object)InjectState.MaskMaterial != (Object)null) { Camera maskCamera = InjectState.MaskCamera; maskCamera.CopyFrom(_cam); maskCamera.depthTextureMode = (DepthTextureMode)0; maskCamera.renderingPath = (RenderingPath)1; maskCamera.allowHDR = false; maskCamera.allowMSAA = false; maskCamera.useOcclusionCulling = false; maskCamera.cullingMask = 1 << InjectState.GrassLayer; maskCamera.SetTargetBuffers(InjectState.ReactiveMask.colorBuffer, InjectState.LowResInput.depthBuffer); maskCamera.clearFlags = (CameraClearFlags)4; RenderTexture active = RenderTexture.active; Graphics.SetRenderTarget(InjectState.ReactiveMask.colorBuffer, InjectState.LowResInput.depthBuffer); GL.Clear(false, true, Color.clear); RenderTexture.active = active; maskCamera.RenderWithShader(InjectState.MaskMaterial.shader, ""); } Matrix4x4 nonJitteredProj = (UpscalerRunner.JitterEnabled ? _cam.nonJitteredProjectionMatrix : _cam.projectionMatrix); bool num2 = UpscalerRunner.TryEvaluate(src, InjectState.Output, _cam, nonJitteredProj); InjectState.ForceResetSubmit = false; if (!num2 && flag && (Object)(object)InjectState.Output != (Object)null) { Graphics.Blit((Texture)(object)src, InjectState.Output); } flag = num2 && UpscalerRunner.NativeEvalEnabled && UpscalerNative.IsWritingOutput(); InjectState.SetOutputFlip(InjectState.FlipOutput && flag); Graphics.Blit((Texture)(object)src, dst); } } public interface IResolutionManager { bool UpdateRenderScale(object upscaledFrameBuffer); float GetQualityScale(); } public class GameControlledResolutionManager : IResolutionManager { public bool UpdateRenderScale(object upscaledFrameBuffer) { return true; } public float GetQualityScale() { if (!InjectState.Enabled) { return 1f; } if ((Object)(object)InjectState.LowResInput != (Object)null && (Object)(object)InjectState.Output != (Object)null && ((Texture)InjectState.Output).width > 0) { return (float)((Texture)InjectState.LowResInput).width / (float)((Texture)InjectState.Output).width; } return 1f; } } public class F2ControlledResolutionManager : IResolutionManager { private FieldInfo _ufbTargetVertical; private FieldInfo _ufbAutoTarget; private bool _ufbLookupFailed; private bool _overrideActive; private uint _savedTargetVertical; private bool _savedAutoTarget; public bool UpdateRenderScale(object upscaledFrameBuffer) { try { if (_ufbLookupFailed) { return true; } if (_ufbTargetVertical == null || _ufbAutoTarget == null) { Type type = upscaledFrameBuffer.GetType(); _ufbTargetVertical = AccessTools.Field(type, "m_targetResolutionVertical"); _ufbAutoTarget = AccessTools.Field(type, "m_autoTargetResolution"); if (_ufbTargetVertical == null || _ufbAutoTarget == null) { _ufbLookupFailed = true; Log.Error("UpscaledFrameBuffer fields renamed (re-run ReconPlugin); leaving vanilla render-scale logic active."); return true; } } if (InjectState.Enabled) { if (!_overrideActive) { _overrideActive = true; _savedTargetVertical = (uint)_ufbTargetVertical.GetValue(null); _savedAutoTarget = (bool)_ufbAutoTarget.GetValue(null); } uint num = (uint)Mathf.Clamp(Mathf.RoundToInt((float)Screen.height * GetQualityScale()), 8, Screen.height - 1); _ufbAutoTarget.SetValue(null, false); _ufbTargetVertical.SetValue(null, num); return false; } Restore(upscaledFrameBuffer); } catch (Exception ex) { Log.Error("Error overriding UpscaledFrameBuffer resolution: " + ex); } return true; } public void Restore(object upscaledFrameBuffer) { if (_overrideActive) { _overrideActive = false; if (_ufbAutoTarget != null) { _ufbAutoTarget.SetValue(null, _savedAutoTarget); } if (_ufbTargetVertical != null) { _ufbTargetVertical.SetValue(null, _savedTargetVertical); } } } public float GetQualityScale() { if (!InjectState.Enabled) { return 1f; } return InjectPlugin.ConfigDLSSMode.Value switch { DlssQuality.Native => 1f, DlssQuality.Quality => 0.67f, DlssQuality.Balanced => 0.58f, DlssQuality.Performance => 0.5f, DlssQuality.UltraPerformance => 0.33f, DlssQuality.Custom => InjectPlugin.ConfigCustomScale.Value, _ => 1f, }; } } public static class ResolutionManagerProvider { private static readonly IResolutionManager _gameControlled = new GameControlledResolutionManager(); private static readonly IResolutionManager _f2Controlled = new F2ControlledResolutionManager(); public static IResolutionManager Current { get { if (InjectPlugin.ConfigCustomResolutionPreset != null && InjectPlugin.ConfigCustomResolutionPreset.Value) { return _f2Controlled; } return _gameControlled; } } public static IResolutionManager F2Controlled => _f2Controlled; } public enum GpuVendor { Unknown, Nvidia, Amd, Intel } internal static class GpuInfo { private static bool _detected; public static GpuVendor Vendor { get; private set; } public static uint VendorId { get; private set; } public static void Detect() { if (_detected) { return; } _detected = true; VendorId = (uint)SystemInfo.graphicsDeviceVendorID; switch (VendorId) { case 4318u: Vendor = GpuVendor.Nvidia; return; case 4098u: case 4130u: Vendor = GpuVendor.Amd; return; case 32902u: case 32903u: Vendor = GpuVendor.Intel; return; } string text = (SystemInfo.graphicsDeviceVendor + " " + SystemInfo.graphicsDeviceName).ToLowerInvariant(); if (text.Contains("nvidia") || text.Contains("geforce")) { Vendor = GpuVendor.Nvidia; } else if (text.Contains("amd") || text.Contains("radeon") || text.Contains("ati ")) { Vendor = GpuVendor.Amd; } else if (text.Contains("intel") || text.Contains("arc")) { Vendor = GpuVendor.Intel; } else { Vendor = GpuVendor.Unknown; } } } internal struct UpscalerFrameParams { public IntPtr Color; public IntPtr Depth; public IntPtr MotionVectors; public IntPtr Output; public IntPtr ReactiveMask; public int RenderWidth; public int RenderHeight; public int DisplayWidth; public int DisplayHeight; public float JitterX; public float JitterY; public float MvScaleX; public float MvScaleY; public int Reset; public int Flags; public float FrameDeltaMs; public IntPtr FgOutputInterp; public int FgEnabled; public int FgNotRenderingGameFrames; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public float[] CamViewToClip; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public float[] ClipToPrevClip; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public float[] PrevClipToClip; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public float[] CamPos; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public float[] CamUp; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public float[] CamRight; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public float[] CamFwd; public float CamNear; public float CamFar; public float CamFovRad; public float CamAspect; public int CamOrtho; } internal static class UpscalerNative { private const string DLL = "ValheimUpscalerNative"; private static IntPtr _eventFunc; public static bool Available { get; private set; } public static IntPtr EventFunc => _eventFunc; public static bool FgAvailable { get; private set; } [DllImport("ValheimUpscalerNative", CallingConvention = CallingConvention.Cdecl)] private static extern int VUP_Init(); [DllImport("ValheimUpscalerNative", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr VUP_GetRenderEventFunc(); [DllImport("ValheimUpscalerNative", CallingConvention = CallingConvention.Cdecl)] private static extern int VUP_IsAvailable(); [DllImport("ValheimUpscalerNative", CallingConvention = CallingConvention.Cdecl)] private static extern int VUP_IsSubmitting(); [DllImport("ValheimUpscalerNative", CallingConvention = CallingConvention.Cdecl)] private static extern void VUP_Shutdown(); [DllImport("ValheimUpscalerNative", CallingConvention = CallingConvention.Cdecl)] private static extern int VUP_IsFgAvailable(); [DllImport("ValheimUpscalerNative", CallingConvention = CallingConvention.Cdecl)] private static extern int VUP_IsFgSubmitting(); [DllImport("ValheimUpscalerNative", CallingConvention = CallingConvention.Cdecl)] private static extern int VUP_GetFrameParamsSize(); [DllImport("ValheimUpscalerNative", CallingConvention = CallingConvention.Cdecl)] private static extern int VUP_GetDlssGStatus(); [DllImport("ValheimUpscalerNative", CallingConvention = CallingConvention.Cdecl)] private static extern int VUP_GetGpuVendor(); [DllImport("ValheimUpscalerNative", CallingConvention = CallingConvention.Cdecl)] private static extern int VUP_HasUnityInterfaces(); [DllImport("ValheimUpscalerNative", CallingConvention = CallingConvention.Cdecl)] private static extern void VUP_EmitLatencyMarker(int markerType, ulong frameId); public static int NativeGpuVendor() { try { return Available ? VUP_GetGpuVendor() : 0; } catch { return 0; } } public static bool IsWritingOutput() { try { return Available && VUP_IsSubmitting() != 0; } catch { return false; } } public static bool IsFgWritingOutput() { try { return Available && VUP_IsFgSubmitting() != 0; } catch { return false; } } public static int DlssGStatus() { try { return Available ? VUP_GetDlssGStatus() : (-1); } catch { return -1; } } public static bool TryLoad() { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Invalid comparison between Unknown and I4 try { int num = VUP_Init(); _eventFunc = VUP_GetRenderEventFunc(); Available = num != 0 && _eventFunc != IntPtr.Zero; int num2 = VUP_IsAvailable(); if (Available && num2 == 0) { Log.Info("Native DLL loaded; backend not confirmed yet (device/NGX init happens lazily on the first dispatched frame). Will dispatch."); } if (Available) { int num3 = VUP_GetFrameParamsSize(); int num4 = Marshal.SizeOf(typeof(UpscalerFrameParams)); if (num3 != num4) { Log.Error($"UpscalerFrameParams SIZE MISMATCH: native={num3} managed={num4} " + "- struct layout drifted between Upscaler.cs and upscaler_native.cpp. Fix before relying on output."); } else { Log.Info($"UpscalerFrameParams size OK ({num4} bytes, native/managed match)."); } } try { FgAvailable = VUP_IsFgAvailable() != 0; } catch { FgAvailable = false; } if (Available && (int)SystemInfo.graphicsDeviceType == 21) { try { if (VUP_HasUnityInterfaces() == 0) { Log.Warning("Vulkan renderer, but UnityPluginLoad never ran - deploy ValheimUpscalerNative.dll into valheim_Data\\Plugins\\x86_64\\ (NOT next to valheim.exe). Native dispatch disabled; bilinear fallback."); Available = false; } } catch (EntryPointNotFoundException) { } } } catch (DllNotFoundException) { Available = false; } catch (EntryPointNotFoundException ex3) { Log.Warning("Native export missing: " + ex3.Message); Available = false; } catch (Exception ex4) { Log.Warning("Native bridge load error: " + ex4.Message); Available = false; } return Available; } public static void Shutdown() { try { if (Available) { VUP_Shutdown(); } } catch { } } public static void EmitLatencyMarker(int type, ulong frameId) { try { if (Available) { VUP_EmitLatencyMarker(type, frameId); } } catch { } } } internal static class UpscalerRunner { private struct CachedNativePtr { public int W; public int H; public IntPtr Ptr; } public static ulong CurrentFrameId; public static bool JitterEnabled = true; public static bool NativeEvalEnabled = true; public static bool ForceMotionVectors = true; public static float CurrentJitterX; public static float CurrentJitterY; private static int _jitterSignMode = 3; public static int JitterReportSignX = -1; public static int JitterReportSignY = -1; private static int _mvSignMode = 3; public static int MvSignX = -1; public static int MvSignY = -1; private static int _jitterIndex; private const int kParamsRing = 4; private static readonly IntPtr[] _paramsRing = new IntPtr[4]; private static int _paramsSlot; private static CommandBuffer _cmd; private static int _lastRW; private static int _lastRH; private static bool _warnedNoDepthMv; private static int _lastSceneIdx = -1; private static Vector3 _lastCamPos; private static bool _forceReset; private static readonly Dictionary _ptrCache = new Dictionary(); private static readonly float[] _camViewToClip = new float[16]; private static readonly float[] _clipToPrevClip = new float[16]; private static readonly float[] _prevClipToClip = new float[16]; private static readonly float[] _camPosArr = new float[3]; private static readonly float[] _camUpArr = new float[3]; private static readonly float[] _camRightArr = new float[3]; private static readonly float[] _camFwdArr = new float[3]; private static Matrix4x4 _prevViewProj = Matrix4x4.identity; private static bool _havePrevViewProj; public static bool FgEnabled { get { if (GpuInfo.Vendor == GpuVendor.Nvidia) { return InjectPlugin.ConfigEnableFG?.Value ?? false; } return false; } } public static int JitterSignMode => _jitterSignMode; public static string JitterSignLabel => string.Format("mode {0} (X{1},Y{2})", _jitterSignMode, (JitterReportSignX > 0) ? "+" : "-", (JitterReportSignY > 0) ? "+" : "-"); public static string MvSignLabel => string.Format("mode {0} (X{1},Y{2})", _mvSignMode, (MvSignX > 0) ? "+" : "-", (MvSignY > 0) ? "+" : "-"); public static void CycleJitterSign() { _jitterSignMode = (_jitterSignMode + 1) % 4; JitterReportSignX = (((_jitterSignMode & 1) == 0) ? 1 : (-1)); JitterReportSignY = (((_jitterSignMode & 2) == 0) ? 1 : (-1)); } public static void CycleMvSign() { _mvSignMode = (_mvSignMode + 1) % 4; MvSignX = (((_mvSignMode & 1) == 0) ? 1 : (-1)); MvSignY = (((_mvSignMode & 2) == 0) ? 1 : (-1)); } private static void FlattenRowMajor(Matrix4x4 m, float[] dst) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) Vector4 row = ((Matrix4x4)(ref m)).GetRow(0); Vector4 row2 = ((Matrix4x4)(ref m)).GetRow(1); Vector4 row3 = ((Matrix4x4)(ref m)).GetRow(2); Vector4 row4 = ((Matrix4x4)(ref m)).GetRow(3); dst[0] = row.x; dst[1] = row.y; dst[2] = row.z; dst[3] = row.w; dst[4] = row2.x; dst[5] = row2.y; dst[6] = row2.z; dst[7] = row2.w; dst[8] = row3.x; dst[9] = row3.y; dst[10] = row3.z; dst[11] = row3.w; dst[12] = row4.x; dst[13] = row4.y; dst[14] = row4.z; dst[15] = row4.w; } public static void Init() { for (int i = 0; i < 4; i++) { _paramsRing[i] = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(UpscalerFrameParams))); } if (UpscalerNative.TryLoad()) { Log.Info("Upscaler native bridge active. Choose the backend (DLSS/FSR/XeSS) in the OptiScaler overlay (Insert)."); } else { Log.Warning("Upscaler native bridge unavailable - using bilinear fallback. Build ValheimUpscalerNative.dll, then drop OptiScaler (as dxgi.dll) next to valheim.exe."); } } public static void ApplyJitter(Camera cam, int renderW, int renderH, ref Matrix4x4 baseProj, ref bool jittered) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) if (!JitterEnabled) { CurrentJitterX = 0f; CurrentJitterY = 0f; return; } cam.ResetProjectionMatrix(); baseProj = cam.projectionMatrix; cam.nonJitteredProjectionMatrix = baseProj; int num = Mathf.Clamp(Mathf.RoundToInt(8f * Mathf.Pow((float)Screen.width / (float)Mathf.Max(1, renderW), 2f)), 8, 64); _jitterIndex = (_jitterIndex + 1) % num; float num2 = Halton(_jitterIndex + 1, 2) - 0.5f; float num3 = Halton(_jitterIndex + 1, 3) - 0.5f; CurrentJitterX = (float)JitterReportSignX * num2; CurrentJitterY = (float)JitterReportSignY * num3; Matrix4x4 projectionMatrix = baseProj; projectionMatrix.m02 += 2f * num2 / (float)renderW; projectionMatrix.m12 += 2f * num3 / (float)renderH; cam.projectionMatrix = projectionMatrix; jittered = true; } public static bool TryEvaluate(RenderTexture src, RenderTexture output, Camera cam, Matrix4x4 nonJitteredProj) { //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_02ed: Unknown result type (might be due to invalid IL or missing references) //IL_02fb: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Unknown result type (might be due to invalid IL or missing references) //IL_0317: Unknown result type (might be due to invalid IL or missing references) //IL_0325: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0524: Unknown result type (might be due to invalid IL or missing references) //IL_0529: Unknown result type (might be due to invalid IL or missing references) //IL_0539: Expected O, but got Unknown if ((Object)(object)output == (Object)null) { return false; } if (!NativeEvalEnabled) { return false; } if (!UpscalerNative.Available) { return false; } Texture globalTexture = Shader.GetGlobalTexture("_CameraDepthTexture"); Texture globalTexture2 = Shader.GetGlobalTexture("_CameraMotionVectorsTexture"); if ((Object)(object)globalTexture == (Object)null || (Object)(object)globalTexture2 == (Object)null) { if (!_warnedNoDepthMv) { _warnedNoDepthMv = true; Log.Warning("Depth/MV not reachable as Textures; upscaler disabled this session (bilinear fallback)."); } return false; } int width = ((Texture)src).width; int height = ((Texture)src).height; IntPtr cachedNativePtr = GetCachedNativePtr((Texture)(object)src); IntPtr cachedNativePtr2 = GetCachedNativePtr(globalTexture); IntPtr cachedNativePtr3 = GetCachedNativePtr(globalTexture2); IntPtr cachedNativePtr4 = GetCachedNativePtr((Texture)(object)output); if (cachedNativePtr == IntPtr.Zero || cachedNativePtr2 == IntPtr.Zero || cachedNativePtr3 == IntPtr.Zero || cachedNativePtr4 == IntPtr.Zero) { return false; } bool num = width != _lastRW || height != _lastRH; Scene activeScene = SceneManager.GetActiveScene(); int buildIndex = ((Scene)(ref activeScene)).buildIndex; bool flag = _lastSceneIdx >= 0 && buildIndex != _lastSceneIdx; Vector3 val = (((Object)(object)cam != (Object)null) ? ((Component)cam).transform.position : Vector3.zero); bool flag2 = _lastSceneIdx >= 0 && Vector3.SqrMagnitude(val - _lastCamPos) > 2500f; int num2 = ((num || flag || flag2 || _forceReset) ? 1 : 0); _lastRW = width; _lastRH = height; _lastSceneIdx = buildIndex; _lastCamPos = val; _forceReset = false; IntPtr cachedNativePtr5 = GetCachedNativePtr((Texture)(object)InjectState.ReactiveMask); IntPtr cachedNativePtr6 = GetCachedNativePtr((Texture)(object)InjectState.FgInterpOutput); int fgEnabled = ((FgEnabled && cachedNativePtr6 != IntPtr.Zero) ? 1 : 0); int fgNotRenderingGameFrames = ((num2 != 0 || Time.timeScale == 0f || !InjectState.Enabled) ? 1 : 0); if ((Object)(object)cam != (Object)null) { FlattenRowMajor(nonJitteredProj, _camViewToClip); Matrix4x4 val2 = nonJitteredProj * cam.worldToCameraMatrix; if (_havePrevViewProj && num2 == 0) { FlattenRowMajor(_prevViewProj * ((Matrix4x4)(ref val2)).inverse, _clipToPrevClip); FlattenRowMajor(val2 * ((Matrix4x4)(ref _prevViewProj)).inverse, _prevClipToClip); } else { FlattenRowMajor(Matrix4x4.identity, _clipToPrevClip); FlattenRowMajor(Matrix4x4.identity, _prevClipToClip); } _prevViewProj = val2; _havePrevViewProj = true; Vector3 position = ((Component)cam).transform.position; Vector3 up = ((Component)cam).transform.up; Vector3 right = ((Component)cam).transform.right; Vector3 forward = ((Component)cam).transform.forward; _camPosArr[0] = position.x; _camPosArr[1] = position.y; _camPosArr[2] = position.z; _camUpArr[0] = up.x; _camUpArr[1] = up.y; _camUpArr[2] = up.z; _camRightArr[0] = right.x; _camRightArr[1] = right.y; _camRightArr[2] = right.z; _camFwdArr[0] = forward.x; _camFwdArr[1] = forward.y; _camFwdArr[2] = forward.z; } UpscalerFrameParams structure = new UpscalerFrameParams { Color = cachedNativePtr, Depth = cachedNativePtr2, MotionVectors = cachedNativePtr3, Output = cachedNativePtr4, ReactiveMask = cachedNativePtr5, RenderWidth = width, RenderHeight = height, DisplayWidth = ((Texture)output).width, DisplayHeight = ((Texture)output).height, JitterX = CurrentJitterX, JitterY = CurrentJitterY, MvScaleX = MvSignX * width, MvScaleY = MvSignY * height, Reset = num2, Flags = 0, FrameDeltaMs = Time.unscaledDeltaTime * 1000f, FgOutputInterp = cachedNativePtr6, FgEnabled = fgEnabled, FgNotRenderingGameFrames = fgNotRenderingGameFrames, CamViewToClip = _camViewToClip, ClipToPrevClip = _clipToPrevClip, PrevClipToClip = _prevClipToClip, CamPos = _camPosArr, CamUp = _camUpArr, CamRight = _camRightArr, CamFwd = _camFwdArr, CamNear = (((Object)(object)cam != (Object)null) ? cam.nearClipPlane : 0.1f), CamFar = (((Object)(object)cam != (Object)null) ? cam.farClipPlane : 1000f), CamFovRad = (((Object)(object)cam != (Object)null) ? (cam.fieldOfView * (MathF.PI / 180f)) : 0f), CamAspect = (((Object)(object)cam != (Object)null) ? cam.aspect : 1f), CamOrtho = (((Object)(object)cam != (Object)null && cam.orthographic) ? 1 : 0) }; _paramsSlot = (_paramsSlot + 1) % 4; IntPtr intPtr = _paramsRing[_paramsSlot]; Marshal.StructureToPtr(structure, intPtr, fDeleteOld: false); if (_cmd == null) { _cmd = new CommandBuffer { name = "ValheimUpscaler" }; } _cmd.Clear(); _cmd.IssuePluginEventAndData(UpscalerNative.EventFunc, 1, intPtr); Graphics.ExecuteCommandBuffer(_cmd); return true; } public static void InvalidateTextureCache() { _ptrCache.Clear(); } private static IntPtr GetCachedNativePtr(Texture tex) { if ((Object)(object)tex == (Object)null) { return IntPtr.Zero; } if (_ptrCache.TryGetValue(tex, out var value) && value.W == tex.width && value.H == tex.height && value.Ptr != IntPtr.Zero) { return value.Ptr; } if (_ptrCache.Count > 64) { _ptrCache.Clear(); } IntPtr nativeTexturePtr = tex.GetNativeTexturePtr(); _ptrCache[tex] = new CachedNativePtr { W = tex.width, H = tex.height, Ptr = nativeTexturePtr }; return nativeTexturePtr; } private static float Halton(int index, int b) { float num = 0f; float num2 = 1f; for (int num3 = index; num3 > 0; num3 /= b) { num2 /= (float)b; num += num2 * (float)(num3 % b); } return num; } public static void Dispose() { UpscalerNative.Shutdown(); if (_cmd != null) { _cmd.Release(); _cmd = null; } for (int i = 0; i < 4; i++) { if (_paramsRing[i] != IntPtr.Zero) { Marshal.FreeHGlobal(_paramsRing[i]); _paramsRing[i] = IntPtr.Zero; } } } } }