Decompiled source of DSPAASR v1.1.0
DSPAAMod.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; using System.Xml; using BepInEx; using BepInEx.Configuration; using DSPAAMod.Core; using DSPAAMod.Game; using DSPAAMod.Interop; using DSPAAMod.UI; using HarmonyLib; using Microsoft.CodeAnalysis; using Unity.Collections; using UnityEngine; using UnityEngine.Events; using UnityEngine.Experimental.Rendering; using UnityEngine.PostProcessing; using UnityEngine.Rendering; using UnityEngine.UI; using UnityStandardAssets.ImageEffects; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("NordLandeW")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Anti-aliasing and super resolution for Dyson Sphere Program.")] [assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyInformationalVersion("1.1.0+35e9ca1fc42d1415477ffb386c310e4fb5df565a")] [assembly: AssemblyProduct("DSPAASR")] [assembly: AssemblyTitle("DSPAAMod")] [assembly: AssemblyVersion("1.1.0.0")] [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 DSPAAMod { [BepInPlugin("dspaa.mod", "DSPAASR", "1.1.0")] [BepInProcess("DSPGAME.exe")] public sealed class Plugin : BaseUnityPlugin { public const string Id = "dspaa.mod"; private ConfigEntry<AaTechnique> technique; private ConfigEntry<ModelSelection> model; private ConfigEntry<ResolutionMode> resolution; private ConfigEntry<float> fsrSharpness; private ConfigEntry<KeyboardShortcut> captureShortcut; private NativeBridge native; private Harmony harmony; private bool stopped; internal static Plugin Instance { get; private set; } internal RenderController Renderer { get; private set; } internal SettingsSession Settings { get; private set; } internal GraphicsOptions Options { get; private set; } private void Awake() { //IL_00ba: 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_01a3: Expected O, but got Unknown Instance = this; try { technique = ((BaseUnityPlugin)this).Config.Bind<AaTechnique>("Antialiasing", "Technique", AaTechnique.Original, "Original preserves game AA; Fxaa/Taa use the game's filters; Dlss/Fsr use the selected resolution mode. Legacy Dlaa migrates to Dlss with native-resolution DLAA. Changing this file requires restart."); model = ((BaseUnityPlugin)this).Config.Bind<ModelSelection>("Antialiasing", "Model", ModelSelection.Recommended, "Recommended: K for DLAA/Quality/Balanced, M for Performance, L for UltraPerformance. Explicit CNN/K/L/M overrides persist independently of resolution mode."); resolution = ((BaseUnityPlugin)this).Config.Bind<ResolutionMode>("Antialiasing", "Resolution", ResolutionMode.Dlaa, "DLSS/FSR resolution mode: Dlaa means native-resolution AA (DLAA or FSR Native AA); SR modes query the selected SDK for actual lower world-render dimensions. Model selection remains independent. Changing this file requires restart."); fsrSharpness = ((BaseUnityPlugin)this).Config.Bind<float>("FSR", "Sharpness", 0f, "FSR RCAS sharpening, 0 (disabled) to 1 (maximum). Independent of DLSS model. Changing this file requires restart."); captureShortcut = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Diagnostics", "CaptureShortcut", new KeyboardShortcut((KeyCode)291, (KeyCode[])(object)new KeyCode[2] { (KeyCode)306, (KeyCode)304 }), "Explicitly trace two Unity frames in LogOutput.log and capture consecutive DLSS submissions (raw color/depth/motion/output) into BepInEx/cache/DSPAAMod/captures. An incomplete pair fails at the end of the trace window. Nothing runs until this shortcut is pressed; captures can be large. Changing this file requires restart."); AaSettings initial; try { initial = new AaSettings(technique.Value, model.Value, resolution.Value, fsrSharpness.Value); } catch (ArgumentOutOfRangeException) { initial = AaSettings.Default; ((BaseUnityPlugin)this).Logger.LogWarning((object)"Invalid settings; using safe defaults without overwriting the config."); } Settings = new SettingsSession(initial); Renderer = new RenderController(initial, AcquireNative, delegate(string text) { ((BaseUnityPlugin)this).Logger.LogWarning((object)text); }, delegate(string text) { ((BaseUnityPlugin)this).Logger.LogInfo((object)text); }); Renderer.Capture = new FrameCapture(Path.Combine(Paths.CachePath, "DSPAAMod", "captures"), delegate(string text) { ((BaseUnityPlugin)this).Logger.LogInfo((object)text); }); Options = new GraphicsOptions(this); harmony = new Harmony("dspaa.mod"); harmony.PatchAll(typeof(Plugin).Assembly); ((BaseUnityPlugin)this).Logger.LogInfo((object)"DSPAASR loaded. DLSS and FSR use the selected AA/SR resolution mode; animated objects may exhibit visual artifacts. No driver settings are modified."); } catch (Exception ex2) { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } Instance = null; ((BaseUnityPlugin)this).Logger.LogError((object)ex2); } } private NativeBridge AcquireNative() { if (native == null) { string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); string dataDirectory = Path.Combine(Paths.CachePath, "DSPAAMod"); native = new NativeBridge(directoryName, dataDirectory); } return native; } internal void ApplySettings() { Settings.Apply(); technique.Value = Settings.Applied.Technique; model.Value = Settings.Applied.Model; resolution.Value = Settings.Applied.Resolution; fsrSharpness.Value = Settings.Applied.FsrSharpness; ((BaseUnityPlugin)this).Config.Save(); Renderer.Configure(Settings.Applied); ((BaseUnityPlugin)this).Logger.LogInfo((object)("AA settings applied: " + Settings.Applied.Technique.ToString() + ", resolution " + Settings.Applied.Resolution.ToString() + ", model " + Settings.Applied.Model)); } internal void Guard(Action action) { try { action(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)ex); } } private void Update() { if ((Object)(object)Instance != (Object)(object)this || stopped) { return; } Guard(delegate { //IL_001c: 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) Renderer.Update(); Options.Update(); KeyboardShortcut value = captureShortcut.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { if (Settings.Applied.Technique == AaTechnique.Dlss) { Renderer.RequestCapture(); } else { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Select DLSS before requesting a frame capture."); } } }); } private void OnDestroy() { if (!((Object)(object)Instance != (Object)(object)this) && !stopped) { stopped = true; Guard(delegate { Renderer.Shutdown(); }); Guard(delegate { Options.Dispose(); }); Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } Instance = null; } } } } namespace DSPAAMod.UI { internal sealed class GraphicsOptions : IDisposable { private static readonly FieldInfo ItemButtonsField = AccessTools.Field(typeof(UIComboBox), "ItemButtons") ?? throw new MissingFieldException(typeof(UIComboBox).FullName, "ItemButtons"); private readonly Plugin plugin; private UIOptionWindow window; private UIComboBox technique; private UIComboBox resolution; private UIComboBox configuration; private RectTransform layoutRoot; private Vector2 originalContentSize; private Vector2 configurationPosition; private Vector2 configurationLabelPosition; private Vector2 availabilityPosition; private Text availabilityLabel; private UpscalerAvailability shownAvailability; private UpscalerAvailability shownFsrAvailability; private float rowStep; private bool originalConfigurationLabelActive; private readonly Dictionary<RectTransform, Vector2> movedRows = new Dictionary<RectTransform, Vector2>(); private AaMenuDraft draft; private Text aaLabel; private Text resolutionLabel; private Text configurationLabel; private Localizer aaLocalizer; private Localizer configurationLocalizer; private string originalAaLabel; private string originalConfigurationLabel; private bool originalAaActive; private bool originalFxaaActive; private bool originalAaLocalized; private bool originalConfigurationLocalized; private bool synchronizing; private int nativeRefreshMsaa; private bool nativeRefreshFxaa; private static bool Chinese => (Localization.CurrentLanguageLCID & 0x3FF) == 4; public GraphicsOptions(Plugin owner) { plugin = owner; } private static int MsaaFromIndex(int index) { return index switch { 3 => 8, 2 => 4, 1 => 2, _ => 0, }; } public void Open(UIOptionWindow value) { plugin.Settings.Open(); plugin.Renderer.RequestUpscalerSupport(); if ((Object)(object)window != (Object)(object)value) { Dispose(); try { Install(value); } catch { Dispose(); throw; } } draft = new AaMenuDraft(plugin.Settings.Draft, MsaaFromIndex(window.msaaComp.itemIndex), window.fxaaComp.isOn); Refresh(); } private void Install(UIOptionWindow value) { //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Expected O, but got Unknown //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Expected O, but got Unknown //IL_0212: 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_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_0338: Unknown result type (might be due to invalid IL or missing references) //IL_033d: Unknown result type (might be due to invalid IL or missing references) //IL_0353: Unknown result type (might be due to invalid IL or missing references) //IL_0358: Unknown result type (might be due to invalid IL or missing references) //IL_035d: Unknown result type (might be due to invalid IL or missing references) //IL_036e: Unknown result type (might be due to invalid IL or missing references) //IL_0373: Unknown result type (might be due to invalid IL or missing references) //IL_0378: Unknown result type (might be due to invalid IL or missing references) //IL_03ab: Unknown result type (might be due to invalid IL or missing references) //IL_03bc: Unknown result type (might be due to invalid IL or missing references) //IL_03c1: Unknown result type (might be due to invalid IL or missing references) //IL_04c4: Unknown result type (might be due to invalid IL or missing references) //IL_04fc: Unknown result type (might be due to invalid IL or missing references) //IL_0502: Expected O, but got Unknown //IL_0582: Unknown result type (might be due to invalid IL or missing references) //IL_0587: Unknown result type (might be due to invalid IL or missing references) //IL_0588: Unknown result type (might be due to invalid IL or missing references) //IL_058f: Unknown result type (might be due to invalid IL or missing references) //IL_05a1: Unknown result type (might be due to invalid IL or missing references) //IL_05ac: Unknown result type (might be due to invalid IL or missing references) //IL_05c9: Unknown result type (might be due to invalid IL or missing references) //IL_05d8: Unknown result type (might be due to invalid IL or missing references) //IL_05dd: Unknown result type (might be due to invalid IL or missing references) //IL_0616: Unknown result type (might be due to invalid IL or missing references) //IL_0620: Expected O, but got Unknown //IL_0632: Unknown result type (might be due to invalid IL or missing references) //IL_063c: Expected O, but got Unknown //IL_064e: Unknown result type (might be due to invalid IL or missing references) //IL_0658: Expected O, but got Unknown //IL_0522: Unknown result type (might be due to invalid IL or missing references) //IL_0527: Unknown result type (might be due to invalid IL or missing references) //IL_052f: Unknown result type (might be due to invalid IL or missing references) //IL_0531: Unknown result type (might be due to invalid IL or missing references) window = value; UIComboBox msaaComp = window.msaaComp; originalAaActive = ((Component)msaaComp).gameObject.activeSelf; originalFxaaActive = ((Component)window.fxaaComp).gameObject.activeSelf; if (msaaComp.Items.Count != 4) { throw new InvalidOperationException("Another mod changed the MSAA list; refusing to overwrite its controls."); } aaLabel = FindLabel(window, "MSAA"); configurationLabel = FindLabel(window, "FXAA"); if (!Object.op_Implicit((Object)(object)aaLabel) || !Object.op_Implicit((Object)(object)configurationLabel)) { throw new InvalidOperationException("Cannot identify the native AA labels by their localization keys."); } originalAaLabel = aaLabel.text; originalConfigurationLabel = configurationLabel.text; originalConfigurationLabelActive = ((Component)configurationLabel).gameObject.activeSelf; aaLocalizer = ((Component)aaLabel).GetComponent<Localizer>(); configurationLocalizer = ((Component)configurationLabel).GetComponent<Localizer>(); if (Object.op_Implicit((Object)(object)aaLocalizer)) { originalAaLocalized = ((Behaviour)aaLocalizer).enabled; ((Behaviour)aaLocalizer).enabled = false; } if (Object.op_Implicit((Object)(object)configurationLocalizer)) { originalConfigurationLocalized = ((Behaviour)configurationLocalizer).enabled; ((Behaviour)configurationLocalizer).enabled = false; } Transform parent = ((Component)msaaComp).transform.parent; Transform parent2 = ((Component)aaLabel).transform.parent; if (!((Object)(object)((Component)configurationLabel).transform.parent != (Object)(object)parent2) && !((Object)(object)((Component)window.fxaaComp).transform.parent != (Object)(object)parent) && !((Object)(object)parent.parent != (Object)(object)parent2.parent)) { Transform parent3 = parent.parent; RectTransform val = (RectTransform)(object)((parent3 is RectTransform) ? parent3 : null); if (val != null) { layoutRoot = val; originalContentSize = val.sizeDelta; RectTransform val2 = (RectTransform)((Component)aaLabel).transform; RectTransform val3 = (RectTransform)((Component)configurationLabel).transform; Rect rect = val2.rect; float y = ((Transform)val).InverseTransformPoint(((Transform)val2).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center))).y; rect = val3.rect; float y2 = ((Transform)val).InverseTransformPoint(((Transform)val3).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center))).y; float num = y - y2; if (num <= 0f) { throw new InvalidOperationException("Invalid graphics-row spacing."); } rowStep = num; ShiftRows(parent2, y2, num); ShiftRows(parent, y2, num); val.sizeDelta = originalContentSize + new Vector2(0f, num); technique = Clone(msaaComp, "DSPAAMod Antialiasing"); resolution = Clone(msaaComp, "DSPAAMod Resolution"); configuration = Clone(msaaComp, "DSPAAMod Configuration"); Transform transform = ((Component)resolution).transform; transform.localPosition += new Vector3(0f, 0f - num, 0f); Transform transform2 = ((Component)configuration).transform; transform2.localPosition += new Vector3(0f, -2f * num, 0f); configurationPosition = ((RectTransform)((Component)configuration).transform).anchoredPosition; configurationLabelPosition = ((RectTransform)((Component)configurationLabel).transform).anchoredPosition; resolutionLabel = Object.Instantiate<Text>(configurationLabel, parent2); ((Object)resolutionLabel).name = "DSPAAMod Resolution Label"; Transform transform3 = ((Component)resolutionLabel).transform; transform3.localPosition += new Vector3(0f, num, 0f); Localizer[] components = ((Component)resolutionLabel).GetComponents<Localizer>(); for (int i = 0; i < components.Length; i++) { ((Behaviour)components[i]).enabled = false; } availabilityLabel = Object.Instantiate<Text>(aaLabel, (Transform)(object)layoutRoot); ((Object)availabilityLabel).name = "DSPAASR Availability"; components = ((Component)availabilityLabel).GetComponents<Localizer>(); for (int i = 0; i < components.Length; i++) { ((Behaviour)components[i]).enabled = false; } availabilityLabel.alignment = (TextAnchor)3; availabilityLabel.supportRichText = false; ((Graphic)availabilityLabel).raycastTarget = false; availabilityLabel.horizontalOverflow = (HorizontalWrapMode)0; availabilityLabel.verticalOverflow = (VerticalWrapMode)0; availabilityLabel.resizeTextForBestFit = true; availabilityLabel.resizeTextMinSize = 11; availabilityLabel.resizeTextMaxSize = 14; ((Graphic)availabilityLabel).color = new Color(1f, 0.82f, 0.55f, 1f); Vector3[] array = (Vector3[])(object)new Vector3[4]; float num2 = float.PositiveInfinity; float num3 = float.NegativeInfinity; RectTransform[] array2 = (RectTransform[])(object)new RectTransform[2] { val2, (RectTransform)((Component)technique).transform }; for (int i = 0; i < array2.Length; i++) { array2[i].GetWorldCorners(array); Vector3[] array3 = array; foreach (Vector3 val4 in array3) { float x = ((Transform)layoutRoot).InverseTransformPoint(val4).x; num2 = Mathf.Min(num2, x); num3 = Mathf.Max(num3, x); } } RectTransform rectTransform = ((Graphic)availabilityLabel).rectTransform; Vector2 anchorMin = (rectTransform.anchorMax = layoutRoot.pivot); rectTransform.anchorMin = anchorMin; rectTransform.pivot = new Vector2(0f, 0.5f); ((Transform)rectTransform).localScale = Vector3.one; rectTransform.sizeDelta = new Vector2(num3 - num2, 2f * num - 4f); availabilityPosition = new Vector2(num2, y); ((Component)msaaComp).gameObject.SetActive(false); ((Component)window.fxaaComp).gameObject.SetActive(false); ((UnityEvent)technique.onItemIndexChange).AddListener(new UnityAction(TechniqueChanged)); ((UnityEvent)resolution.onItemIndexChange).AddListener(new UnityAction(ResolutionChanged)); ((UnityEvent)configuration.onItemIndexChange).AddListener(new UnityAction(ConfigurationChanged)); return; } } throw new InvalidOperationException("Unexpected graphics-row hierarchy; refusing to shift unrelated controls."); } private void ShiftRows(Transform column, float fromCenter, float distance) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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_006f: 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) foreach (Transform item in column) { object obj = (object)item; RectTransform val = (RectTransform)((obj is RectTransform) ? obj : null); if (val != null) { RectTransform obj2 = layoutRoot; Rect rect = val.rect; if (!(((Transform)obj2).InverseTransformPoint(((Transform)val).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center))).y > fromCenter + 0.5f)) { movedRows.Add(val, val.anchoredPosition); val.anchoredPosition += new Vector2(0f, 0f - distance); } } } } private static UIComboBox Clone(UIComboBox source, string name) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown UIComboBox val = Object.Instantiate<UIComboBox>(source, ((Component)source).transform.parent); try { ((Object)val).name = name; val.InitItemIndexSelf = false; val.CanInput = false; val.translated = true; val.autoWidth = false; val.DoubleClickChange = false; val.isDroppedDown = false; val.onItemIndexChange = new ChangeEvent(); val.onSubmit = new SubmitEvent(); val.Items = new List<string>(); val.ItemsData = new List<int>(); Localizer[] componentsInChildren = ((Component)val).GetComponentsInChildren<Localizer>(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Behaviour)componentsInChildren[i]).enabled = false; } foreach (Transform item in (Transform)val.m_DropDownContent) { Transform val2 = item; if (!((Object)(object)val2 == (Object)(object)((Component)val.m_ListItemRes).transform) && !((Object)(object)val2 == (Object)(object)((Component)val.m_EmptyItemRes).transform) && !((Object)(object)val2 == (Object)(object)((Component)val.m_SelectionBG).transform)) { ((Component)val2).gameObject.SetActive(false); Object.Destroy((Object)(object)((Component)val2).gameObject); } } ((Component)val).gameObject.SetActive(true); return val; } catch { Object.Destroy((Object)(object)((Component)val).gameObject); throw; } } private static Text FindLabel(UIOptionWindow owner, string key) { Localizer[] componentsInChildren = ((Component)owner).GetComponentsInChildren<Localizer>(true); foreach (Localizer val in componentsInChildren) { if (AaLabels.Matches(val.stringKey, key) || AaLabels.Matches(((Object)val).name, key)) { Text component = ((Component)val).GetComponent<Text>(); if (Object.op_Implicit((Object)(object)component)) { return component; } } } string text = Localization.Translate(key); Text[] componentsInChildren2 = ((Component)owner).GetComponentsInChildren<Text>(true); foreach (Text val2 in componentsInChildren2) { if (val2.text.Trim() == text || AaLabels.Matches(val2.text, key)) { return val2; } } return null; } private static void SetItems(UIComboBox control, string[] items, int index) { control.isDroppedDown = false; control.Items = new List<string>(items); control.ItemsData = new List<int>(); for (int i = 0; i < items.Length; i++) { control.ItemsData.Add(i); } control.UpdateItems(); control.itemIndex = index; } private void TechniqueChanged() { if (!synchronizing && draft != null && Object.op_Implicit((Object)(object)technique) && technique.itemIndex >= 0 && technique.itemIndex <= 5) { if (!draft.TrySelectTechnique((AaChoice)technique.itemIndex, plugin.Renderer.GetAvailability((AaChoice)technique.itemIndex))) { Refresh(); return; } plugin.Settings.Draft = draft.Settings; Refresh(); } } private void ResolutionChanged() { if (!synchronizing && draft != null && Object.op_Implicit((Object)(object)resolution) && draft.ResolutionEnabled && plugin.Renderer.GetAvailability(draft.Choice).Available && resolution.itemIndex >= 0 && resolution.itemIndex <= 4) { draft.SelectResolution((ResolutionMode)resolution.itemIndex); plugin.Settings.Draft = draft.Settings; } } private void ConfigurationChanged() { if (!synchronizing && draft != null && Object.op_Implicit((Object)(object)configuration) && draft.ConfigurationEnabled && configuration.itemIndex >= 0 && (draft.Choice != AaChoice.Dlss || plugin.Renderer.Availability.Available)) { draft.SelectConfiguration(configuration.itemIndex); plugin.Settings.Draft = draft.Settings; } } public void DropdownOpened(UIComboBox control) { if (Object.op_Implicit((Object)(object)window) && Object.op_Implicit((Object)(object)layoutRoot) && control.isDroppedDown && ((Component)control).transform.IsChildOf((Transform)(object)layoutRoot)) { Transform val = ((Component)control).transform; while (Object.op_Implicit((Object)(object)val) && (Object)(object)val != (Object)(object)layoutRoot) { val.SetAsLastSibling(); val = val.parent; } } } public void BeginNativeRefresh() { synchronizing = true; } public void EndNativeRefresh() { if (Object.op_Implicit((Object)(object)window)) { nativeRefreshMsaa = MsaaFromIndex(window.msaaComp.itemIndex); nativeRefreshFxaa = window.fxaaComp.isOn; } synchronizing = false; Refresh(); } public void Update() { if (Object.op_Implicit((Object)(object)window) && draft != null && (shownAvailability != plugin.Renderer.Availability || shownFsrAvailability != plugin.Renderer.FsrAvailability)) { Refresh(); } } public void Refresh() { if (!Object.op_Implicit((Object)(object)window) || !Object.op_Implicit((Object)(object)technique) || !Object.op_Implicit((Object)(object)resolution) || !Object.op_Implicit((Object)(object)configuration) || draft == null) { return; } synchronizing = true; try { aaLabel.text = (Chinese ? "抗锯齿 / 超分辨率" : "AA / Super Resolution"); resolutionLabel.text = (Chinese ? "超分辨率档位" : "Resolution mode"); configurationLabel.text = (Chinese ? "配置" : "Configuration"); shownAvailability = plugin.Renderer.Availability; shownFsrAvailability = plugin.Renderer.FsrAvailability; SetItems(technique, new string[6] { Chinese ? "关闭" : "Off", "MSAA", "FXAA", "TAA", CapabilityLabel(shownAvailability), CapabilityLabel(shownFsrAvailability) }, (int)draft.Choice); List<Button> obj = (List<Button>)ItemButtonsField.GetValue(technique); ((Selectable)obj[4]).interactable = shownAvailability.Available; ((Selectable)obj[5]).interactable = shownFsrAvailability.Available; string text = shownAvailability.Describe(Chinese); string text2 = shownFsrAvailability.Describe(Chinese); availabilityLabel.text = text + ((text.Length > 0 && text2.Length > 0) ? "\n" : "") + text2; SetItems(resolution, new string[5] { (draft.Choice == AaChoice.Fsr) ? "Native AA" : "DLAA", Chinese ? "质量" : "Quality", Chinese ? "平衡" : "Balanced", Chinese ? "性能" : "Performance", Chinese ? "超级性能" : "Ultra Performance" }, (int)draft.Settings.Resolution); string[] items = ((draft.Choice != AaChoice.Dlss) ? ((draft.Choice != AaChoice.Msaa) ? new string[1] { Chinese ? "无" : "None" } : new string[3] { "2×", "4×", "8×" }) : new string[5] { Chinese ? "推荐" : "Recommended", "CNN", "Transformer K", "Transformer L", "Transformer M" }); SetItems(configuration, items, draft.ConfigurationIndex); RefreshLayout(); } finally { synchronizing = false; } } private static string CapabilityLabel(UpscalerAvailability state) { return state.Name + (state.Available ? "" : ((!state.Pending) ? (Chinese ? "(不可用)" : " (unavailable)") : (Chinese ? "(检测中)" : " (checking)"))); } private void RefreshLayout() { //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) int num = ((!plugin.Renderer.Availability.Available) ? 2 : 0) + ((!plugin.Renderer.FsrAvailability.Available) ? 2 : 0); bool active = num != 0; bool available = plugin.Renderer.GetAvailability(draft.Choice).Available; bool flag = draft.ResolutionEnabled && available; bool flag2 = draft.ConfigurationEnabled && (draft.Choice != AaChoice.Dlss || available); ((Component)resolution).gameObject.SetActive(flag); ((Component)resolutionLabel).gameObject.SetActive(flag); ((Component)configuration).gameObject.SetActive(flag2); ((Component)configurationLabel).gameObject.SetActive(flag2); int num2 = (flag ? 1 : 0) + (flag2 ? 1 : 0); int num3 = num2 + num; ((Graphic)availabilityLabel).rectTransform.sizeDelta = new Vector2(((Graphic)availabilityLabel).rectTransform.sizeDelta.x, (float)Mathf.Max(1, num) * rowStep - 4f); ((Component)availabilityLabel).gameObject.SetActive(active); ((Transform)((Graphic)availabilityLabel).rectTransform).localPosition = new Vector3(availabilityPosition.x, availabilityPosition.y - rowStep * ((float)num2 + 0.5f + (float)num * 0.5f), 0f); Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0f, rowStep * (float)(1 - num3)); foreach (KeyValuePair<RectTransform, Vector2> movedRow in movedRows) { if (Object.op_Implicit((Object)(object)movedRow.Key)) { movedRow.Key.anchoredPosition = movedRow.Value + val; } } ((RectTransform)((Component)configuration).transform).anchoredPosition = configurationPosition + new Vector2(0f, flag ? 0f : rowStep); ((RectTransform)((Component)configurationLabel).transform).anchoredPosition = configurationLabelPosition + new Vector2(0f, flag ? 0f : rowStep); layoutRoot.sizeDelta = originalContentSize - val; } public void Read(ref GameOption option) { if (draft != null && Object.op_Implicit((Object)(object)window)) { option.msaa = draft.NativeMsaa; option.fxaa = draft.NativeFxaa; plugin.Settings.Draft = draft.Settings; } } public void Close() { plugin.Settings.Cancel(); draft = null; } public void Defaults(int tab) { if (tab == 0) { plugin.Settings.Defaults(); draft = new AaMenuDraft(plugin.Settings.Draft, nativeRefreshMsaa, nativeRefreshFxaa); Refresh(); } } public void Dispose() { //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)technique)) { ((Component)technique).gameObject.SetActive(false); Object.Destroy((Object)(object)((Component)technique).gameObject); } if (Object.op_Implicit((Object)(object)resolution)) { ((Component)resolution).gameObject.SetActive(false); Object.Destroy((Object)(object)((Component)resolution).gameObject); } if (Object.op_Implicit((Object)(object)resolutionLabel)) { ((Component)resolutionLabel).gameObject.SetActive(false); Object.Destroy((Object)(object)((Component)resolutionLabel).gameObject); } if (Object.op_Implicit((Object)(object)availabilityLabel)) { ((Component)availabilityLabel).gameObject.SetActive(false); Object.Destroy((Object)(object)((Component)availabilityLabel).gameObject); } availabilityLabel = null; shownAvailability = (shownFsrAvailability = null); foreach (KeyValuePair<RectTransform, Vector2> movedRow in movedRows) { if (Object.op_Implicit((Object)(object)movedRow.Key)) { movedRow.Key.anchoredPosition = movedRow.Value; } } movedRows.Clear(); if (Object.op_Implicit((Object)(object)layoutRoot)) { layoutRoot.sizeDelta = originalContentSize; } layoutRoot = null; if (Object.op_Implicit((Object)(object)configuration)) { ((Component)configuration).gameObject.SetActive(false); Object.Destroy((Object)(object)((Component)configuration).gameObject); } if (Object.op_Implicit((Object)(object)window)) { ((Component)window.msaaComp).gameObject.SetActive(originalAaActive); ((Component)window.fxaaComp).gameObject.SetActive(originalFxaaActive); } if (Object.op_Implicit((Object)(object)aaLabel) && originalAaLabel != null) { aaLabel.text = originalAaLabel; } if (Object.op_Implicit((Object)(object)configurationLabel) && originalConfigurationLabel != null) { configurationLabel.text = originalConfigurationLabel; ((Component)configurationLabel).gameObject.SetActive(originalConfigurationLabelActive); } if (Object.op_Implicit((Object)(object)aaLocalizer)) { ((Behaviour)aaLocalizer).enabled = originalAaLocalized; } if (Object.op_Implicit((Object)(object)configurationLocalizer)) { ((Behaviour)configurationLocalizer).enabled = originalConfigurationLocalized; } window = null; technique = (resolution = (configuration = null)); aaLabel = (resolutionLabel = (configurationLabel = null)); aaLocalizer = (configurationLocalizer = null); draft = null; } } [HarmonyPatch(typeof(UIOptionWindow), "_OnOpen")] internal static class OptionsOpenPatch { private static void Postfix(UIOptionWindow __instance) { Plugin.Instance?.Guard(delegate { Plugin.Instance.Options.Open(__instance); }); } } [HarmonyPatch(typeof(UIOptionWindow), "_OnClose")] internal static class OptionsClosePatch { private static void Postfix() { Plugin.Instance?.Options.Close(); } } [HarmonyPatch(typeof(UIOptionWindow), "TempOptionToUI")] internal static class OptionsRefreshPatch { private static void Prefix() { Plugin.Instance?.Options.BeginNativeRefresh(); } private static void Postfix() { Plugin.Instance?.Guard(delegate { Plugin.Instance.Options.EndNativeRefresh(); }); } } [HarmonyPatch(typeof(UIOptionWindow), "UIToTempOption")] internal static class OptionsReadPatch { private static void Postfix(ref GameOption ___tempOption) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_0035: Unknown result type (might be due to invalid IL or missing references) GameOption value = ___tempOption; Plugin.Instance?.Guard(delegate { Plugin.Instance.Options.Read(ref value); }); ___tempOption = value; } } [HarmonyPatch(typeof(UIOptionWindow), "ApplyOptions")] internal static class OptionsApplyPatch { private static void Prefix(ref GameOption ___tempOption) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_0035: Unknown result type (might be due to invalid IL or missing references) GameOption value = ___tempOption; Plugin.Instance?.Guard(delegate { Plugin.Instance.Options.Read(ref value); }); ___tempOption = value; } private static void Postfix() { Plugin.Instance?.Guard(delegate { Plugin.Instance.ApplySettings(); }); } } [HarmonyPatch(typeof(UIOptionWindow), "OnLanguageChange")] internal static class OptionsLanguagePatch { private static void Postfix() { Plugin.Instance?.Guard(delegate { Plugin.Instance.Options.Refresh(); }); } } [HarmonyPatch(typeof(UIComboBox), "OnPopButtonClick")] internal static class AaDropdownPatch { private static void Postfix(UIComboBox __instance) { Plugin.Instance?.Guard(delegate { Plugin.Instance.Options.DropdownOpened(__instance); }); } } [HarmonyPatch(typeof(UIOptionWindow), "OnRevertButtonClick")] internal static class OptionsDefaultsPatch { private static void Postfix(int idx) { Plugin.Instance?.Guard(delegate { Plugin.Instance.Options.Defaults(idx); }); } } } namespace DSPAAMod.Interop { public struct NativeFrame { public uint Size; public uint Version; public ulong Camera; public ulong Frame; public IntPtr Color; public IntPtr Output; public IntPtr Depth; public IntPtr Motion; public uint Width; public uint Height; public uint Preset; public uint Flags; public float JitterX; public float JitterY; public float MotionScaleX; public float MotionScaleY; public float FrameTimeMilliseconds; public uint Reserved; public uint OutputWidth; public uint OutputHeight; public uint Quality; public uint Reserved2; } public struct NativeFsrParameters { public uint Size; public float CameraNear; public float CameraFar; public float VerticalFov; public float PreExposure; public float ViewSpaceToMeters; public float Sharpness; public uint Reserved; public IntPtr OpaqueColor; } public struct NativeFsrOptimalSettings { public NativeOptimalSettings Settings; public uint JitterPhases; } public struct NativeStatus { public uint Size; public int Result; public ulong Frame; public uint RequestedPreset; public uint ObservedPreset; public uint Verification; public uint Reserved; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] public byte[] MessageBytes; public string Message { get { if (MessageBytes == null) { return string.Empty; } int num = Array.IndexOf(MessageBytes, (byte)0); return Encoding.UTF8.GetString(MessageBytes, 0, (num < 0) ? MessageBytes.Length : num); } } } public struct NativeOptimalSettings { public uint Size; public int Result; public uint OutputWidth; public uint OutputHeight; public uint Quality; public uint OptimalWidth; public uint OptimalHeight; public uint MinWidth; public uint MinHeight; public uint MaxWidth; public uint MaxHeight; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] public byte[] MessageBytes; public string Message { get { if (MessageBytes == null) { return string.Empty; } int num = Array.IndexOf(MessageBytes, (byte)0); return Encoding.UTF8.GetString(MessageBytes, 0, (num < 0) ? MessageBytes.Length : num); } } } public struct NativeSupport { public uint Size; public int Result; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] public byte[] MessageBytes; public string Message { get { if (MessageBytes == null) { return string.Empty; } int num = Array.IndexOf(MessageBytes, (byte)0); return Encoding.UTF8.GetString(MessageBytes, 0, (num < 0) ? MessageBytes.Length : num); } } } public sealed class NativeBridge { [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate uint Abi(); [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Unicode)] private delegate int Initialize(string runtime, string data); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate IntPtr GetEvent(); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate IntPtr QueueFrame(ref NativeFrame frame); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate IntPtr QueueRelease(ulong camera); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate IntPtr QueueShutdown(); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void CancelCommand(IntPtr token); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate int ReadStatus(ulong camera, ref NativeStatus status); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate IntPtr QueueOptimal(ulong camera, IntPtr deviceResource, uint width, uint height, uint quality); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate int ReadOptimal(ulong camera, ref NativeOptimalSettings settings); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate IntPtr QueueSupport(IntPtr deviceResource); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate int ReadSupport(IntPtr token, ref NativeSupport support); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate IntPtr QueueFsrFrame(ref NativeFrame frame, ref NativeFsrParameters parameters); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate IntPtr QueueBackendSupport(IntPtr resource, uint backend); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate IntPtr QueueBackendOptimal(ulong camera, IntPtr resource, uint width, uint height, uint quality, uint backend); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate int ReadFsrOptimal(ulong camera, ref NativeFsrOptimalSettings result); private readonly IntPtr module; private readonly QueueFrame queueFrame; private readonly QueueRelease queueRelease; private readonly QueueShutdown queueShutdown; private readonly CancelCommand cancel; private readonly ReadStatus readStatus; private readonly QueueOptimal queueOptimal; private readonly ReadOptimal readOptimal; private readonly QueueSupport queueSupport; private readonly ReadSupport readSupport; private readonly QueueFsrFrame queueFsrFrame; private readonly QueueBackendSupport queueBackendSupport; private readonly QueueBackendOptimal queueBackendOptimal; private readonly ReadFsrOptimal readFsrOptimal; public IntPtr RenderEvent { get; } public static uint FrameSize => (uint)Marshal.SizeOf(typeof(NativeFrame)); public static uint StatusSize => (uint)Marshal.SizeOf(typeof(NativeStatus)); public static uint OptimalSize => (uint)Marshal.SizeOf(typeof(NativeOptimalSettings)); public static uint SupportSize => (uint)Marshal.SizeOf(typeof(NativeSupport)); public static uint FsrParametersSize => (uint)Marshal.SizeOf(typeof(NativeFsrParameters)); public static uint FsrOptimalSize => (uint)Marshal.SizeOf(typeof(NativeFsrOptimalSettings)); [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern IntPtr LoadLibraryEx(string name, IntPtr file, uint flags); [DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] private static extern IntPtr GetProcAddress(IntPtr module, string name); public NativeBridge(string directory, string dataDirectory) { if (!Environment.Is64BitProcess) { throw new PlatformNotSupportedException("DSPAAMod requires x64."); } module = LoadLibraryEx(Path.Combine(directory, "DSPAANative.dll"), IntPtr.Zero, 4352u); if (module == IntPtr.Zero) { throw new Win32Exception(Marshal.GetLastWin32Error(), "Cannot load DSPAANative.dll."); } if (Get<Abi>("DspAaGetAbiVersion")() != 2 || FrameSize != 112 || StatusSize != 288 || OptimalSize != 300 || SupportSize != 264 || FsrParametersSize != 40 || FsrOptimalSize != 304) { throw new InvalidOperationException("Native/managed DSPAAMod ABI mismatch."); } queueFrame = Get<QueueFrame>("DspAaQueueFrame"); queueRelease = Get<QueueRelease>("DspAaQueueRelease"); queueShutdown = Get<QueueShutdown>("DspAaQueueShutdown"); cancel = Get<CancelCommand>("DspAaCancel"); readStatus = Get<ReadStatus>("DspAaGetStatus"); queueOptimal = Get<QueueOptimal>("DspAaQueueOptimalSettings"); readOptimal = Get<ReadOptimal>("DspAaGetOptimalSettings"); queueSupport = Get<QueueSupport>("DspAaQueueSupport"); readSupport = Get<ReadSupport>("DspAaGetSupport"); queueFsrFrame = Get<QueueFsrFrame>("DspAaQueueFsrFrame"); queueBackendSupport = Get<QueueBackendSupport>("DspAaQueueSupportForBackend"); queueBackendOptimal = Get<QueueBackendOptimal>("DspAaQueueOptimalSettingsForBackend"); readFsrOptimal = Get<ReadFsrOptimal>("DspAaGetFsrOptimalSettings"); RenderEvent = Get<GetEvent>("DspAaGetRenderEvent")(); if (RenderEvent == IntPtr.Zero || Get<Initialize>("DspAaInitialize")(directory, dataDirectory) != 1) { throw new InvalidOperationException("Native bridge initialization failed; check runtime path and log permissions."); } } private T Get<T>(string name) where T : Delegate { IntPtr procAddress = GetProcAddress(module, name); if (procAddress == IntPtr.Zero) { throw new EntryPointNotFoundException(name); } return (T)Marshal.GetDelegateForFunctionPointer(procAddress, typeof(T)); } public IntPtr Submit(ref NativeFrame frame) { frame.Size = FrameSize; frame.Version = 2u; return queueFrame(ref frame); } public IntPtr SubmitFsr(ref NativeFrame frame, ref NativeFsrParameters parameters) { frame.Size = FrameSize; frame.Version = 2u; parameters.Size = FsrParametersSize; return queueFsrFrame(ref frame, ref parameters); } public IntPtr RequestOptimal(ulong camera, IntPtr resource, uint width, uint height, uint quality, uint backend) { return queueBackendOptimal(camera, resource, width, height, quality, backend); } public bool TryGetFsrOptimal(ulong camera, out NativeFsrOptimalSettings result) { result = new NativeFsrOptimalSettings { Settings = new NativeOptimalSettings { Size = FsrOptimalSize, MessageBytes = new byte[256] } }; return readFsrOptimal(camera, ref result) == 1; } public IntPtr RequestSupport(IntPtr resource, uint backend) { return queueBackendSupport(resource, backend); } public IntPtr RequestOptimal(ulong camera, IntPtr deviceResource, uint width, uint height, uint quality) { return queueOptimal(camera, deviceResource, width, height, quality); } public bool TryGetOptimal(ulong camera, out NativeOptimalSettings result) { result = new NativeOptimalSettings { Size = OptimalSize, MessageBytes = new byte[256] }; return readOptimal(camera, ref result) == 1; } public IntPtr RequestSupport(IntPtr deviceResource) { return queueSupport(deviceResource); } public bool TryGetSupport(IntPtr token, out NativeSupport result) { result = new NativeSupport { Size = SupportSize, MessageBytes = new byte[256] }; return readSupport(token, ref result) == 1; } public IntPtr Release(ulong camera) { return queueRelease(camera); } public IntPtr Shutdown() { return queueShutdown(); } public void Cancel(IntPtr token) { if (token != IntPtr.Zero) { cancel(token); } } public bool TryGetStatus(ulong camera, out NativeStatus status) { status = new NativeStatus { Size = StatusSize, MessageBytes = new byte[256] }; return readStatus(camera, ref status) == 1; } } } namespace DSPAAMod.Game { internal sealed class FrameCapture { private sealed class Resource { public string Name; public string File; public string Error; public string Hash; public int Width; public int Height; public readonly Dictionary<string, string> Metadata = new Dictionary<string, string>(); public byte[] Bytes; public bool Claimed; } private sealed class Frame { public NativeFrame Native; public int UnityFrame; public readonly Dictionary<string, string> Metadata = new Dictionary<string, string>(); public readonly List<Resource> Resources = new List<Resource>(); } private sealed class Group { public string Id; public string Directory; public RenderTargets Targets; public readonly List<Frame> Frames = new List<Frame>(); public readonly List<string> Errors = new List<string>(); public int Pending; public bool Sealed; public bool Writing; } private readonly string directory; private readonly Action<string> log; private readonly object gate = new object(); private readonly Dictionary<RenderTargets, int> pending = new Dictionary<RenderTargets, int>(); private Group active; public FrameCapture(string directory, Action<string> log) { this.directory = directory; this.log = log; } public bool Request() { lock (gate) { if (active != null) { Log("Frame capture request ignored: a capture is already armed or in progress."); return false; } try { string id = DateTime.UtcNow.ToString("yyyyMMdd-HHmmss-fff", CultureInfo.InvariantCulture) + "-" + Guid.NewGuid().ToString("N"); Group obj = new Group { Id = id, Directory = Path.Combine(directory, id) }; if (Directory.Exists(obj.Directory)) { throw new IOException("Capture directory already exists."); } Directory.CreateDirectory(obj.Directory); WriteDocument(Path.Combine(obj.Directory, "request.xml"), "captureRequest", delegate(XmlWriter writer) { Value(writer, "id", id); Value(writer, "requestedUtc", DateTime.UtcNow.ToString("O", CultureInfo.InvariantCulture)); Value(writer, "frameCount", 2); Value(writer, "state", "armed; result.xml is the terminal record"); }); active = obj; if (!SystemInfo.supportsAsyncGPUReadback) { Fail(obj, "AsyncGPUReadback is unsupported on this device."); FinishIfReady(obj); } else { Log("Frame capture armed for two consecutive submissions from the first captured camera: " + obj.Directory); } return true; } catch (Exception ex) { Log("Cannot arm frame capture: " + ex.Message); if (active != null) { Fail(active, "Cannot finish arming capture: " + ex.Message); FinishIfReady(active); } return false; } } } public bool IsBusy(RenderTargets targets) { lock (gate) { int value; return targets != null && pending.TryGetValue(targets, out value) && value != 0; } } public void Cancel(string reason) { lock (gate) { if (active != null && !active.Sealed) { Fail(active, "Capture cancelled: " + reason); FinishIfReady(active); } } } public void Cancel(RenderTargets targets, string reason) { lock (gate) { if (active != null && active.Targets == targets) { Cancel(reason); } } } public void EnqueueIfRequested(NativeFrame native, RenderTargets targets, Camera camera, Matrix4x4 renderedProjection, int deferredWorldTextCount) { //IL_0582: Unknown result type (might be due to invalid IL or missing references) //IL_0588: Unknown result type (might be due to invalid IL or missing references) //IL_0520: Unknown result type (might be due to invalid IL or missing references) //IL_0525: Unknown result type (might be due to invalid IL or missing references) //IL_0550: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0369: Unknown result type (might be due to invalid IL or missing references) //IL_0386: Unknown result type (might be due to invalid IL or missing references) //IL_03a3: Unknown result type (might be due to invalid IL or missing references) //IL_03c0: Unknown result type (might be due to invalid IL or missing references) //IL_03ca: Expected I4, but got Unknown //IL_0422: Unknown result type (might be due to invalid IL or missing references) //IL_0428: Invalid comparison between Unknown and I4 //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) lock (gate) { Group group = active; if (group == null || group.Sealed) { return; } if (group.Frames.Count != 0) { Frame frame = group.Frames[0]; int frameCount = Time.frameCount; if (native.Camera != frame.Native.Camera && frameCount <= frame.UnityFrame + 1) { return; } if (native.Camera != frame.Native.Camera || targets != group.Targets || native.Frame != frame.Native.Frame + 1 || frameCount != frame.UnityFrame + 1) { Fail(group, "Expected the same camera/targets on consecutive native and Unity frames; got native " + frame.Native.Frame + " -> " + native.Frame + ", Unity " + frame.UnityFrame + " -> " + frameCount + "."); FinishIfReady(group); return; } } try { if (targets == null || (Object)(object)camera == (Object)null) { throw new InvalidOperationException("Capture has no live targets/camera."); } Frame frame2 = new Frame { Native = native }; SnapshotFrame(frame2, camera, renderedProjection, deferredWorldTextCount); RenderTexture[] array = (RenderTexture[])(object)new RenderTexture[4] { targets.Color, targets.Depth, targets.Motion, targets.Output }; string[] array2 = new string[4] { "color", "depth", "motion", "output" }; for (int i = 0; i < array.Length; i++) { RenderTexture val = array[i]; if (!Object.op_Implicit((Object)(object)val) || !val.IsCreated()) { throw new InvalidOperationException(array2[i] + " texture is not created."); } if (!SystemInfo.IsFormatSupported(val.graphicsFormat, (FormatUsage)9)) { throw new NotSupportedException(array2[i] + " format does not support unconverted readback: " + ((object)val.graphicsFormat/*cast due to .constrained prefix*/).ToString()); } Resource resource = new Resource(); resource.Name = array2[i]; resource.File = "frame-" + group.Frames.Count + "-" + array2[i] + ".raw"; resource.Width = ((Texture)val).width; resource.Height = ((Texture)val).height; Resource resource2 = resource; Add(resource2.Metadata, "width", ((Texture)val).width); Add(resource2.Metadata, "height", ((Texture)val).height); Add(resource2.Metadata, "volumeDepth", val.volumeDepth); Add(resource2.Metadata, "dimension", ((Texture)val).dimension); Add(resource2.Metadata, "renderTextureFormat", val.format); Add(resource2.Metadata, "graphicsFormat", val.graphicsFormat); Add(resource2.Metadata, "graphicsFormatValue", (int)val.graphicsFormat); Add(resource2.Metadata, "antiAliasing", val.antiAliasing); Add(resource2.Metadata, "sRGB", val.sRGB); Add(resource2.Metadata, "mip", 0); if ((int)((Texture)val).dimension != 2 || val.volumeDepth != 1) { throw new NotSupportedException("Capture expects single-layer 2D render textures."); } frame2.Resources.Add(resource2); } group.Targets = targets; group.Frames.Add(frame2); group.Sealed = group.Frames.Count == 2; group.Pending += array.Length; pending.TryGetValue(targets, out var value); pending[targets] = value + array.Length; for (int j = 0; j < array.Length; j++) { Resource resource3 = frame2.Resources[j]; try { AsyncGPUReadbackRequest request = AsyncGPUReadback.Request((Texture)(object)array[j], 0, (Action<AsyncGPUReadbackRequest>)delegate(AsyncGPUReadbackRequest completed) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) Complete(group, targets, resource3, completed, null); }); if (((AsyncGPUReadbackRequest)(ref request)).hasError) { Complete(group, targets, resource3, request, "GPU readback request failed."); } } catch (Exception ex) { Complete(group, targets, resource3, default(AsyncGPUReadbackRequest), "Cannot submit readback: " + ex.Message); } } } catch (Exception ex2) { Fail(group, "Cannot capture submitted frame: " + ex2.Message); FinishIfReady(group); } } } private void Complete(Group group, RenderTargets targets, Resource resource, AsyncGPUReadbackRequest request, string failure) { //IL_0127: 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) lock (gate) { if (resource.Claimed) { return; } resource.Claimed = true; } try { if (failure != null) { throw new InvalidOperationException(failure); } if (!((AsyncGPUReadbackRequest)(ref request)).done || ((AsyncGPUReadbackRequest)(ref request)).hasError) { throw new InvalidOperationException("GPU readback did not complete successfully."); } Add(resource.Metadata, "readbackWidth", ((AsyncGPUReadbackRequest)(ref request)).width); Add(resource.Metadata, "readbackHeight", ((AsyncGPUReadbackRequest)(ref request)).height); Add(resource.Metadata, "readbackDepth", ((AsyncGPUReadbackRequest)(ref request)).depth); Add(resource.Metadata, "layerCount", ((AsyncGPUReadbackRequest)(ref request)).layerCount); Add(resource.Metadata, "layerDataSize", ((AsyncGPUReadbackRequest)(ref request)).layerDataSize); if (((AsyncGPUReadbackRequest)(ref request)).layerCount != 1 || ((AsyncGPUReadbackRequest)(ref request)).depth != 1 || ((AsyncGPUReadbackRequest)(ref request)).width != resource.Width || ((AsyncGPUReadbackRequest)(ref request)).height != resource.Height) { throw new InvalidOperationException("Readback dimensions do not match the snapshotted 2D texture."); } NativeArray<byte> data = ((AsyncGPUReadbackRequest)(ref request)).GetData<byte>(0); if (data.Length == 0) { throw new InvalidOperationException("Readback returned no bytes."); } resource.Bytes = new byte[data.Length]; data.CopyTo(resource.Bytes); } catch (Exception ex) { resource.Error = ex.Message; } finally { lock (gate) { if (resource.Error != null) { Fail(group, resource.File + ": " + resource.Error); } group.Pending--; if (--pending[targets] == 0) { pending.Remove(targets); } FinishIfReady(group); } } } private void FinishIfReady(Group group) { if (!group.Sealed || group.Pending != 0 || group.Writing) { return; } group.Writing = true; group.Targets = null; try { Task.Run(delegate { Persist(group); }); } catch (Exception ex) { Log("Cannot schedule capture persistence; request.xml remains incomplete: " + ex.Message); if (active == group) { active = null; } } } private void Persist(Group group) { try { for (int i = 0; i < group.Frames.Count; i++) { Frame frame = group.Frames[i]; foreach (Resource resource in frame.Resources) { if (resource.Bytes == null) { continue; } try { using (FileStream fileStream = new FileStream(Path.Combine(group.Directory, resource.File), FileMode.CreateNew, FileAccess.Write, FileShare.Read)) { fileStream.Write(resource.Bytes, 0, resource.Bytes.Length); } using (SHA256 sHA = SHA256.Create()) { resource.Hash = BitConverter.ToString(sHA.ComputeHash(resource.Bytes)).Replace("-", ""); } Add(resource.Metadata, "byteLength", resource.Bytes.Length); } catch (Exception ex) { resource.Error = "Cannot persist raw data: " + ex.Message; group.Errors.Add(resource.File + ": " + resource.Error); } finally { resource.Bytes = null; } } try { WriteDocument(Path.Combine(group.Directory, "frame-" + i + ".xml"), "submittedFrame", delegate(XmlWriter writer) { foreach (KeyValuePair<string, string> metadatum in frame.Metadata) { Value(writer, metadatum.Key, metadatum.Value); } foreach (Resource resource2 in frame.Resources) { writer.WriteStartElement("resource"); writer.WriteAttributeString("name", resource2.Name); Value(writer, "file", resource2.File); Value(writer, "success", resource2.Error == null && resource2.Hash != null); Value(writer, "sha256", resource2.Hash ?? ""); Value(writer, "error", resource2.Error ?? ""); foreach (KeyValuePair<string, string> metadatum2 in resource2.Metadata) { Value(writer, metadatum2.Key, metadatum2.Value); } writer.WriteEndElement(); } }); } catch (Exception ex2) { group.Errors.Add("Cannot persist frame metadata: " + ex2.Message); } } bool success = group.Frames.Count == 2 && group.Errors.Count == 0; WriteDocument(Path.Combine(group.Directory, "result.xml"), "captureResult", delegate(XmlWriter writer) { Value(writer, "id", group.Id); Value(writer, "completedUtc", DateTime.UtcNow.ToString("O", CultureInfo.InvariantCulture)); Value(writer, "success", success); Value(writer, "capturedFrames", group.Frames.Count); Value(writer, "expectedFrames", 2); Value(writer, "meaning", "Success means raw readback and persistence only; correlate NGX logs to verify evaluation/model."); foreach (string error in group.Errors) { Value(writer, "error", error); } }); Log("Frame capture " + (success ? "complete: " : "failed; see result.xml: ") + group.Directory); foreach (string error2 in group.Errors) { Log("Frame capture: " + error2); } } catch (Exception ex3) { Log("Cannot write terminal capture result at " + group.Directory + ": " + ex3.Message); } finally { lock (gate) { if (active == group) { active = null; } } } } private static void SnapshotFrame(Frame frame, Camera camera, Matrix4x4 renderedProjection, int deferredWorldTextCount) { //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: 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_02da: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02ec: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_031a: Unknown result type (might be due to invalid IL or missing references) //IL_0330: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Unknown result type (might be due to invalid IL or missing references) //IL_035b: Unknown result type (might be due to invalid IL or missing references) //IL_036c: Unknown result type (might be due to invalid IL or missing references) //IL_036e: Unknown result type (might be due to invalid IL or missing references) Dictionary<string, string> metadata = frame.Metadata; NativeFrame native = frame.Native; Add(metadata, "capturedUtc", DateTime.UtcNow.ToString("O", CultureInfo.InvariantCulture)); Add(metadata, "nativeAbiVersion", native.Version); Add(metadata, "nativeCameraId", native.Camera); Add(metadata, "nativeFrameId", native.Frame); frame.UnityFrame = Time.frameCount; Add(metadata, "unityFrameCount", frame.UnityFrame); Add(metadata, "unityTime", Time.time); Add(metadata, "unityUnscaledTime", Time.unscaledTime); Add(metadata, "unityRealtimeSinceStartup", Time.realtimeSinceStartup); Add(metadata, "unityUnscaledDeltaTime", Time.unscaledDeltaTime); Add(metadata, "deferredWorldTextCount", deferredWorldTextCount); Add(metadata, "worldTextObservation", "When deferredWorldTextCount is nonzero, navigation glyphs are excluded from these NGX inputs/output and drawn afterward into the temporal resolve destination."); Add(metadata, "cameraInstanceId", ((Object)camera).GetInstanceID()); Add(metadata, "cameraName", ((Object)camera).name); Add(metadata, "inputWidth", native.Width); Add(metadata, "inputHeight", native.Height); Add(metadata, "outputWidth", native.OutputWidth); Add(metadata, "outputHeight", native.OutputHeight); Add(metadata, "requestedPresetValue", native.Preset); Add(metadata, "requestedPreset", (native.Preset >= 1 && native.Preset <= 26) ? ((char)(65 + native.Preset - 1)).ToString() : "unknown"); Add(metadata, "observedModel", "unknown; correlate the NGX log, not the requested preset"); Add(metadata, "qualityValue", native.Quality); Add(metadata, "flags", native.Flags); Add(metadata, "reset", (native.Flags & 4) != 0); Add(metadata, "jitterX", native.JitterX); Add(metadata, "jitterY", native.JitterY); Add(metadata, "motionScaleX", native.MotionScaleX); Add(metadata, "motionScaleY", native.MotionScaleY); Add(metadata, "frameTimeMilliseconds", native.FrameTimeMilliseconds); Add(metadata, "cameraPosition", Vector(((Component)camera).transform.position)); Quaternion rotation = ((Component)camera).transform.rotation; Add(metadata, "cameraRotationXYZW", Join(rotation.x, rotation.y, rotation.z, rotation.w)); Add(metadata, "worldToCameraMatrixRowMajor", Matrix(camera.worldToCameraMatrix)); Add(metadata, "cameraToWorldMatrixRowMajor", Matrix(camera.cameraToWorldMatrix)); Add(metadata, "projectionMatrixRowMajor", Matrix(camera.projectionMatrix)); Add(metadata, "nonJitteredProjectionMatrixRowMajor", Matrix(camera.nonJitteredProjectionMatrix)); Add(metadata, "renderProjectionMatrixRowMajor", Matrix(renderedProjection)); Add(metadata, "gpuProjectionForRenderTextureRowMajor", Matrix(GL.GetGPUProjectionMatrix(renderedProjection, true))); Add(metadata, "projectionObservation", "Camera projection is snapshotted at submission after OnPostRender; renderProjection preserves the matrix used for this world draw."); Add(metadata, "rawEncoding", "Unconverted graphicsFormat bytes from mip0/layer0; no vertical flip or channel conversion."); Add(metadata, "littleEndianHost", BitConverter.IsLittleEndian); } private static string Vector(Vector3 value) { //IL_0008: 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_001a: Unknown result type (might be due to invalid IL or missing references) return Join(value.x, value.y, value.z); } private static string Join(params float[] values) { return string.Join(" ", Array.ConvertAll(values, (float v) => v.ToString("R", CultureInfo.InvariantCulture))); } private static string Matrix(Matrix4x4 value) { float[] array = new float[16]; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { array[i * 4 + j] = ((Matrix4x4)(ref value))[i, j]; } } return Join(array); } private static string Format(object value) { if (value is bool) { if (!(bool)value) { return "false"; } return "true"; } if (value is float num) { return num.ToString("R", CultureInfo.InvariantCulture); } if (value is double num2) { return num2.ToString("R", CultureInfo.InvariantCulture); } return Convert.ToString(value, CultureInfo.InvariantCulture); } private static void Add(IDictionary<string, string> data, string name, object value) { data.Add(name, Format(value)); } private static void Value(XmlWriter writer, string name, object value) { writer.WriteElementString(name, Format(value)); } private static void WriteDocument(string path, string root, Action<XmlWriter> write) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown using FileStream fileStream = new FileStream(path, FileMode.CreateNew, FileAccess.Write, FileShare.Read); XmlWriter val = XmlWriter.Create((Stream)fileStream, new XmlWriterSettings { Indent = true, Encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false) }); try { val.WriteStartDocument(); val.WriteStartElement(root); write(val); val.WriteEndElement(); val.WriteEndDocument(); } finally { ((IDisposable)val)?.Dispose(); } } private void Fail(Group group, string error) { group.Errors.Add(error); group.Sealed = true; Log("Frame capture: " + error); } private void Log(string message) { try { log?.Invoke(message); } catch { } } } internal sealed class RenderController { internal sealed class CameraState { public Camera Camera; public PostProcessingBehaviour Behaviour; public ulong Key; public RenderTargets Targets; public RenderTexture SizingAnchor; public RenderTexture OriginalTarget; public RenderTexture ImageResult; public SrPresentation Presenter; public CommandBuffer OpaqueCapture; public readonly WorldTextOverlay WorldText = new WorldTextOverlay(); public bool ReportedWorldText; public int WorldTextFrame = -1; public int RequestedWidth; public int RequestedHeight; public bool QueryIssued; public bool TargetOverridden; public bool SrThisRender; public bool InputsCopied; public Matrix4x4 AppliedProjection; public uint Phase; public ulong Frame; public uint ReportedPreset; public int LastFrame = -1; public int Scene = -1; public int Profile; public Vector3 Position; public Quaternion Rotation; public Matrix4x4 Projection; public JitterSample Jitter; public bool Reset = true; public bool Faulted; public bool Prepared; public bool JitterApplied; public bool Overridden; public bool OriginalMsaa; public bool OriginalTransparentJitter; public AntialiasingModel Model; public Settings OriginalSettings; public bool OriginalEnabled; } internal sealed class ImageScope { public CameraState State; public RenderTexture OriginalDestination; public RenderTexture Target; public RenderTexture Source; public bool TemporalStack; } private sealed class SupportQuery { public UpscalerAvailability Availability; public RenderTexture Anchor; public IntPtr Token; } private readonly Dictionary<RenderTexture, CameraState> imageSources = new Dictionary<RenderTexture, CameraState>(); private readonly Dictionary<Camera, CameraState> cameras = new Dictionary<Camera, CameraState>(); private readonly List<CameraState> retired = new List<CameraState>(); private readonly Action<string> report; private readonly Action<string> information; private readonly Func<NativeBridge> acquireNative; private readonly Action<TaaComponent, Vector2> setJitter; private NativeBridge native; private readonly SupportQuery[] supportQueries = new SupportQuery[2]; private bool supportRequested; private ulong nextKey; private AaSettings settings; private int diagnosticThrough = -1; private static readonly FieldInfo ContextField = AccessTools.Field(typeof(PostProcessingBehaviour), "m_Context"); public FrameCapture Capture { get; set; } public UpscalerAvailability Availability => supportQueries[0].Availability; public UpscalerAvailability FsrAvailability => supportQueries[1].Availability; private bool FsrSelected => settings.Technique == AaTechnique.Fsr; private UpscalerAvailability ActiveAvailability { get { if (!FsrSelected) { return Availability; } return FsrAvailability; } } private string BackendName { get { if (!FsrSelected) { return "DLSS"; } return "FSR"; } } private bool DiagnosticActive { get { if (diagnosticThrough >= 0) { return Time.frameCount <= diagnosticThrough; } return false; } } public string Status { get; private set; } = "Original game AA; DLAA not enabled."; public UpscalerAvailability GetAvailability(AaChoice choice) { if (choice != AaChoice.Fsr) { return Availability; } return FsrAvailability; } public void RequestCapture() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown if (diagnosticThrough < 0 && Capture != null && Capture.Request()) { diagnosticThrough = Time.frameCount + 1; Camera.onPreCull = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(TraceCameraCull)); Camera.onPostRender = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(TraceCameraPost)); TraceOverview("requested"); } } private void TraceCameraCull(Camera camera) { TraceStage("camera.preCull", camera); } private void TraceCameraPost(Camera camera) { TraceStage("camera.postRender", camera); } private void FinishDiagnostic() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown if (diagnosticThrough >= 0) { Camera.onPreCull = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(TraceCameraCull)); Camera.onPostRender = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(TraceCameraPost)); diagnosticThrough = -1; TraceOverview("window-complete"); Capture?.Cancel("The two-frame diagnostic window ended without two consecutive DLSS submissions; inspect PipelineTrace in LogOutput.log."); } } private void TraceOverview(string phase) { //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) try { information("PipelineTrace " + phase + " unityFrame=" + Time.frameCount + " scene=" + GameCamera.sceneIndex + " planet=" + ((GameMain.localPlanet == null) ? "space" : GameMain.localPlanet.id.ToString()) + " selected=" + settings.Technique.ToString() + "/" + settings.Resolution.ToString() + " status=" + Status); Camera[] allCameras = Camera.allCameras; foreach (Camera val in allCameras) { List<string> list = new List<string>(); MonoBehaviour[] components = ((Component)val).GetComponents<MonoBehaviour>(); foreach (MonoBehaviour val2 in components) { if (Object.op_Implicit((Object)(object)val2)) { list.Add(((object)val2).GetType().FullName + ":enabled=" + ((Behaviour)val2).enabled); } } information("PipelineTrace camera=" + ((Object)val).GetInstanceID() + ":" + ((Object)val).name + " depth=" + val.depth + " mask=" + val.cullingMask + " viewport=" + ((object)val.pixelRect/*cast due to .constrained prefix*/).ToString() + " target=" + TextureDescription(val.targetTexture) + " components=" + string.Join(",", list)); if (cameras.TryGetValue(val, out var value)) { TraceNative(value); } } } catch (Exception ex) { report("PipelineTrace overview failed: " + ex.Message); } } private void TraceNative(CameraState state) { if (native != null && native.TryGetStatus(state.Key, out var status)) { information("PipelineTrace nativeLatest cameraKey=" + state.Key + " submitted=" + state.Frame + " completed=" + status.Frame + " result=" + status.Result + " requested=" + status.RequestedPreset + " observed=" + status.ObservedPreset + " message=" + status.Message); } else { information("PipelineTrace nativeLatest cameraKey=" + state.Key + " submitted=" + state.Frame + " no-completion-record"); } } private static string TextureDescription(RenderTexture texture) { if (!Object.op_Implicit((Object)(object)texture)) { return "backbuffer"; } return ((Object)texture).name + ":" + ((Texture)texture).width + "x" + ((Texture)texture).height; } private unsafe void TraceStage(string stage, Camera camera, PostProcessingContext context = null, RenderTexture source = null, RenderTexture destination = null) { //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) if (!DiagnosticActive) { return; } try { if (!Object.op_Implicit((Object)(object)camera)) { information("PipelineTrace stage=" + stage + " no-camera"); return; } PostProcessingBehaviour component = ((Component)camera).GetComponent<PostProcessingBehaviour>(); if (context == null && Object.op_Implicit((Object)(object)component) && ContextField != null) { object? value = ContextField.GetValue(component); context = (PostProcessingContext)((value is PostProcessingContext) ? value : null); } PostProcessingProfile val = (Object.op_Implicit((Object)(object)component) ? component.profile : context?.profile); object obj; if (!Object.op_Implicit((Object)(object)val)) { obj = " no-profile"; } else { string[] obj2 = new string[8] { " profile=", ((Object)val).GetInstanceID().ToString(), " enabled=", ((PostProcessingModel)val.antialiasing).enabled.ToString(), " method=", null, null, null }; Settings val2 = val.antialiasing.settings; obj2[5] = ((object)(*(Method*)(&val2.method))/*cast due to .constrained prefix*/).ToString(); obj2[6] = " debugInterrupt="; obj2[7] = val.debugViews.willInterrupt.ToString(); obj = string.Concat(obj2); } string text = (string)obj; text = text + " contextProfile=" + ((context != null && Object.op_Implicit((Object)(object)context.profile)) ? ((Object)context.profile).GetInstanceID().ToString() : "none"); CameraState value2; string text2 = (cameras.TryGetValue(camera, out value2) ? (" key=" + value2.Key + " prepared=" + value2.Prepared + " faulted=" + value2.Faulted + " reset=" + value2.Reset + " jitterApplied=" + value2.JitterApplied + " submitted=" + value2.Frame) : " unregistered-camera"); information("PipelineTrace frame=" + Time.frameCount + " stage=" + stage + " camera=" + ((Object)camera).GetInstanceID() + ":" + ((Object)camera).name + " postEnabled=" + (Object.op_Implicit((Object)(object)component) && ((Behaviour)component).enabled) + text + " interrupted=" + (context != null && context.interrupted) + text2 + " source=" + TextureDescription(source) + " destination=" + TextureDescription(destination)); } catch (Exception ex) { report("PipelineTrace stage failed: " + ex.Message); } } public RenderController(AaSettings initial, Func<NativeBridge> acquire, Action<string> log, Action<string> info) { //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Invalid comparison between Unknown and I4 settings = initial; acquireNative = acquire; report = log; information = info; setJitter = AccessTools.MethodDelegate<Action<TaaComponent, Vector2>>(AccessTools.PropertySetter(typeof(TaaComponent), "jitterVector"), (object)null, true); for (int i = 0; i < supportQueries.Length; i++) { supportQueries[i] = new SupportQuery { Availability = UpscalerAvailability.ForPlatform((int)SystemInfo.graphicsDeviceType == 2, SystemInfo.graphicsDeviceVendorID, SystemInfo.supportsMotionVectors, SystemInfo.supportsComputeShaders, (UpscalerBackend)i) }; } } public void RequestUpscalerSupport() { supportRequested = true; } private void UpdateSupport(SupportQuery query) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown if (!query.Availability.Pending) { return; } try { NativeSupport result; if (query.Token == IntPtr.Zero) { if (native == null) { native = acquireNative(); } query.Anchor = new RenderTexture(2, 2, 0, (RenderTextureFormat)0) { name = "DSPAASR capability device anchor", hideFlags = (HideFlags)61 }; if (!query.Anchor.Create()) { throw new InvalidOperationException("Cannot allocate a graphics-device query anchor."); } IntPtr intPtr = native.RequestSupport(((Texture)query.Anchor).GetNativeTexturePtr(), (uint)query.Availability.Backend); if (intPtr == IntPtr.Zero) { throw new InvalidOperationException("Cannot queue the " + query.Availability.Name + " capability check."); } IssueControl(intPtr); query.Token = intPtr; } else if (native.TryGetSupport(query.Token, out result) && result.Result != 0) { query.Token = IntPtr.Zero; DestroyAnchor(query.Anchor); query.Anchor = null; query.Availability = query.Availability.Complete(result.Result == 1, result.Message); if (!query.Availability.Available) { report(query.Availability.Describe(chinese: false)); } } } catch (Exception ex) { if (query.Token == IntPtr.Zero) { DestroyAnchor(query.Anchor); query.Anchor = null; } query.Availability = query.Availability.Complete(available: false, ex.Message); report(query.Availability.Describe(chinese: false)); } } public void Configure(AaSettings value) { Capture?.Cancel("AA settings changed."); foreach (CameraState value2 in cameras.Values) { Restore(value2); if (Object.op_Implicit((Object)(object)value2.Behaviour)) { value2.Behaviour.ResetTemporalEffects(); } Retire(value2); } cameras.Clear(); settings = value; Status = (value.Temporal ? "Waiting for a compatible camera." : ("Using " + value.Technique)); } public void BeforeCull(PostProcessingBehaviour behaviour) { //IL_0677: Unknown result type (might be due to invalid IL or missing references) //IL_067c: Unknown result type (might be due to invalid IL or missing references) //IL_06a1: Unknown result type (might be due to invalid IL or missing references) //IL_06a6: Unknown result type (might be due to invalid IL or missing references) //IL_06bb: Unknown result type (might be due to invalid IL or missing references) //IL_06c6: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Invalid comparison between Unknown and I4 //IL_03ef: Unknown result type (might be due to invalid IL or missing references) //IL_03f4: Unknown result type (might be due to invalid IL or missing references) //IL_0423: Unknown result type (might be due to invalid IL or missing references) //IL_043c: Unknown result type (might be due to invalid IL or missing references) //IL_0491: Unknown result type (might be due to invalid IL or missing references) //IL_056d: Unknown result type (might be due to invalid IL or missing references) //IL_0572: Unknown result type (might be due to invalid IL or missing references) //IL_057e: Unknown result type (might be due to invalid IL or missing references) //IL_0583: Unknown result type (might be due to invalid IL or missing references) //IL_0589: Unknown result type (might be due to invalid IL or missing references) //IL_058b: Unknown result type (might be due to invalid IL or missing references) //IL_04d0: Unknown result type (might be due to invalid IL or missing references) //IL_04db: Unknown result type (might be due to invalid IL or missing references) //IL_04e0: Unknown result type (might be due to invalid IL or missing references) //IL_04e5: Unknown result type (might be due to invalid IL or missing references) //IL_05ff: Unknown result type (might be due to invalid IL or missing references) //IL_05b4: Unknown result type (might be due to invalid IL or missing references) //IL_05b9: Unknown result type (might be due to invalid IL or missing references) //IL_05c9: Expected O, but got Unknown //IL_05d0: Unknown result type (might be due to invalid IL or missing references) //IL_05e0: Unknown result type (might be due to invalid IL or missing references) //IL_04f6: Unknown result type (might be due to invalid IL or missing references) //IL_0501: Unknown result type (might be due to invalid IL or missing references) //IL_0513: Unknown result type (might be due to invalid IL or missing references) //IL_0518: Unknown result type (might be due to invalid IL or missing references) if (DiagnosticActive && Object.op_Implicit((Object)(object)behaviour)) { TraceStage("post.preCull-entry", ((Component)behaviour).GetComponent<Camera>()); } if (!Object.op_Implicit((Object)(object)behaviour) || !Object.op_Implicit((Object)(object)behaviour.profile)) { return; } Camera component = ((Component)behaviour).GetComponent<Camera>(); if (!Object.op_Implicit((Object)(object)component) || settings.Technique == AaTechnique.Original) { return; } if (!cameras.TryGetValue(component, out var value)) { bool flag = false; PostEffectController[] array = Object.FindObjectsOfType<PostEffectController>(); for (int i = 0; i < array.Length; i++) { if ((Object)(object)array[i].postScript == (Object)(object)behaviour) { flag = true; break; } } if (!flag) { return; } value = new CameraState { Camera = component, Behaviour = behaviour, Key = ++nextKey }; cameras.Add(component, value); } Restore(value); value.Prepared = false; value.SrThisRender = false; value.InputsCopied = false; value.ImageResult = null; if (settings.Technique == AaTechnique.Original) { return; } if (settings.Temporal) { if (!ActiveAvailability.Available) { Status = ActiveAvailability.Describe(chinese: false); if (Object.op_Implicit((Object)(object)value.Presenter)) { ((Behaviour)value.Presenter).enabled = false; } return; } if (value.Faulted) { if (Object.op_Implicit((Object)(object)value.Presenter)) { ((Behaviour)value.Presenter).enabled = false; } return; } try { if ((int)SystemInfo.graphicsDeviceType != 2 || !SystemInfo.supportsMotionVectors || !SystemInfo.supportsComputeShaders || (!FsrSelected && SystemInfo.graphicsDeviceVendorID != 4318) || component.stereoEnabled) { throw new NotSupportedException(BackendName + " requires compatible D3D11, motion vectors, compute support and a non-stereo camera."); } if (FsrSelected && component.orthographic) { throw new NotSupportedException("FSR's depth reconstruction requires a perspective camera."); } if (behaviour.profile.debugViews.willInterrupt) { return; } if (native == null) { native = acquireNative(); } if (native.TryGetStatus(value.Key, out var status)) { if (status.Result < 0) { Fail(value, status.Message); return; } if (status.Result == 1) { string[] obj = new string[12] { BackendName, " ", settings.Resolution.ToString(), " | ", value.Targets.Width.ToString(), "x", value.Targets.Height.ToString(), " -> ", null, null, null, null }; int i = value.Targets.Resolution.OutputWidth; obj[8] = i.ToString(); obj[9] = "x"; i = value.Targets.Resolution.OutputHeight; obj[10] = i.ToString(); obj[11] = (FsrSelected ? (" | " + status.Message) : (" | requested " + (char)(65 + status.RequestedPreset - 1) + " | observed " + (char)status.ObservedPreset + " | runtime-log verified")); Status = string.Concat(obj); uint num = (FsrSelected ? 1u : status.ObservedPreset); if (value.ReportedPreset != num) { information(Status); value.ReportedPreset = num; } } } if ((settings.Resolution != ResolutionMode.Dlaa && Object.op_Implicit((Object)(object)component.targetTexture)) || component.pixelWidth <= 0 || component.pixelHeight <= 0) { return; } Matrix4x4 projectionMatrix = component.projectionMatrix; if (!PrepareTargets(value, component.pixelWidth, component.pixelHeight)) { return; } if (!value.Targets.Resolution.IsNative) { if (component.rect != new Rect(0f, 0f, 1f, 1f)) { value.Reset = true; Status = "Original AA for a partial camera viewport; SR resumes at full viewport."; return; } EnsurePresentation(value); value.OriginalTarget = component.targetTexture; value.TargetOverridden = true; value.SrThisRender = true; component.targetTexture = value.Targets.World; component.projectionMatrix = projectionMatrix; } int sceneIndex = GameCamera.sceneIndex; int instanceID = ((Object)behaviour.profile).GetInstanceID(); if (value.LastFrame + 1 == Time.frameCount && value.Scene == sceneIndex && value.Profile == instanceID) { Vector3 val = value.Position - ((Component)component).transform.position; if (!(((Vector3)(ref val)).sqrMagnitude > 100f) && !(Quaternion.Angle(value.Rotation, ((Component)component).transform.rotation) > 30f) && !(value.Projection != projectionMatrix)) { goto IL_0528; } } value.Reset = true; goto IL_0528; IL_0528: if (value.Reset) { value.Phase = 0u; } value.Jitter = Jitter.ForFrame(value.Phase++, value.Targets.Resolution.JitterPhases); value.Position = ((Component)component).transform.position; value.Rotation = ((Component)component).transform.rotation; value.Projection = projectionMatrix; value.Scene = sceneIndex; value.Profile = instanceID; value.LastFrame = Time.frameCount; if (FsrSelected) { value.OpaqueCapture = new CommandBuffer { name = "DSPAASR FSR opaque color" }; value.OpaqueCapture.Blit(RenderTargetIdentifier.op_Implicit((BuiltinRenderTextureType)2), RenderTargetIdentifier.op_Implicit((Texture)(object)value.Targets.OpaqueColor)); component.AddCommandBuffer((CameraEvent)16, value.OpaqueCapture); } value.WorldText.Begin(component, projectionMatrix); value.WorldTextFrame = Time.frameCount; } catch (Exception ex) { Restore(value); value.SrThisRender = false; if (Object.op_Implicit((Object)(object)value.Presenter)) { ((Behaviour)value.Presenter).enabled = false; } Fail(value, ex.Message); return; } } value.Model = behaviour.profile.antialiasing; value.OriginalEnabled = ((PostProcessingModel)value.Model).enabled; value.OriginalSettings = value.Model.settings; value.OriginalMsaa = component.allowMSAA; value.OriginalTransparentJitter = component.useJitteredProjectionMatrixForTransparentRendering; value.Overridden = true; Settings originalSettings = value.OriginalSettings; originalSettings.method = (Method)(settings.Technique != AaTechnique.Fxaa); value.Model.settings = originalSettings; ((PostProcessingModel)value.Model).enabled = true; if (settings.Temporal) { component.allowMSAA = false; } value.Prepared = settings.Temporal; TraceStage("post.preCull-prepared", component); } private bool PrepareTargets(CameraState state, int width, int height) { //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown if (state.RequestedWidth != width || state.RequestedHeight != height || (state.Targets != null && !state.Targets.Valid)) { Retire(state); state.Key = ++nextKey; state.RequestedWidth = width; state.RequestedHeight = height; state.ReportedPreset = 0u; state.Reset = true; } if (state.Targets != null) { return true; } RenderResolution resolution = new RenderResolution(width, height, width, height); if (settings.Resolution != ResolutionMode.Dlaa || FsrSelected) { if (!state.QueryIssued) { state.SizingAnchor = new RenderTexture(2, 2, 0, (RenderTextureFormat)2, (RenderTextureReadWrite)1) { name = "DSPAAMod sizing device anchor", hideFlags = (HideFlags)61 }; if (!state.SizingAnchor.Create()) { throw new InvalidOperationException("Cannot allocate reconstruction sizing anchor."); } IntPtr token = native.RequestOptimal(state.Key, ((Texture)state.SizingAnchor).GetNativeTexturePtr(), (uint)width, (uint)height, (uint)settings.Resolution, FsrSelected ? 1u : 0u); IssueControl(token); state.QueryIssued = true; Status = "Querying " + BackendName + " render size for " + settings.Resolution; return false; } uint num = 0u; NativeOptimalSettings result2; if (FsrSelected) { if (!native.TryGetFsrOptimal(state.Key, out var result) || result.Settings.Result == 0) { return false; } result2 = result.Settings; num = result.JitterPhases; if (result2.Result == 1 && num == 0) { throw new InvalidOperationException("FSR returned no jitter sequence."); } } else if (!native.TryGetOptimal(state.Key, out result2) || result2.Result == 0) { return false; } if (result2.Result < 0) { throw new InvalidOperationException(result2.Message); } if (result2.OutputWidth != (uint)width || result2.OutputHeight != (uint)height || result2.Quality != (uint)settings.Resolution) { throw new InvalidOperationException("Stale reconstruction resolution response."); } resolution = checked(new RenderResolution((int)result2.OptimalWidth, (int)result2.OptimalHeight, width, height, num)); DestroyAnchor(state.SizingAnchor); state.SizingAnchor = null; } state.Targets = new RenderTargets(resolution, FsrSelected); Action<string> action = information; string[] obj = new string[13] { BackendName, " render targets: ", null, null, null, null, null, null, null, null, null, null, null }; int inputWidth = resolution.InputWidth; obj[2] = inputWidth.ToString(); obj[3] = "x"; inputWidth = resolution.InputHeight; obj[4] = inputWidth.ToString(); obj[5] = " world -> "; obj[6] = width.ToString(); obj[7] = "x"; obj[8] = height.ToString(); obj[9] = " output/UI, mode "; obj[10] = settings.Resolution.ToString(); obj[11] = ", jitter phases "; obj[12] = resolution.JitterPhases.ToString(); action(string.Concat(obj)); return true; } private static void EnsurePresentation(CameraState state) { if (!Object.op_Implicit((Object)(object)state.Presenter)) { state.Presenter = ((Component)state.Camera).GetComponent<SrPresentation>(); } if (!Object.op_Implicit((Object)(object)state.Presenter)) { state.Presenter = ((Component)state.Camera).gameObject.AddComponent<SrPresentation>(); } ((Behaviour)state.Presenter).enabled = true; bool flag = false; bool flag2 = false; MonoBehaviour[] components = ((Component)state.Camera).GetComponents<MonoBehaviour>(); foreach (MonoBehaviour val in components) { if (Object.op_Implicit((Object)(object)val) && ((Behaviour)val).isActiveAndEnabled) { if ((Object)(object)val == (Object)(object)state.Behaviour) { flag = true; } if ((Object)(object)val == (Object)(object)state.Presenter) { flag2 = true; } else if (flag && HasImageEffect(((object)val).GetType()) && (flag2 || ((Object)(object)val != (Object)(object)state.Behaviour && !(val is TranslucentImageSource) && !(val is SunShafts)))) { throw new NotSupportedException("Unintegrated image effect after the reconstruction stack: " + ((object)val).GetType().FullName); } } } } private static bool HasImageEffect(Type type) { Type[] types = new Type[2] { typeof(RenderTexture), typeof(RenderTexture) }; while (type != null) { if (type.GetMethod("OnRenderImage", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, types, null) != null) { return true; } type = type.BaseType; } return false; } private static void RestoreTarget(CameraState state) { if (state.TargetOverridden) { if (Object.op_Implicit((Object)(object)state.Camera) && state.Targets != null && (Object)(object)state.Camera.targetTexture == (Object)(object)state.Targets.World) { state.Camera.targetTexture = state.OriginalTarget; } state.TargetOverridden = false; } } private static void DestroyA