game: Fix compat with iGPUs, add fix for stuck DLSS option with blinker
This commit is contained in:
parent
64690df48b
commit
ec59c46440
5 changed files with 162 additions and 21 deletions
|
@ -125,7 +125,29 @@ public enum ResolutionScalingMode
|
|||
|
||||
public static class ResolutionScalingModeExt
|
||||
{
|
||||
public static byte ToXIV(this ResolutionScalingMode mode) => mode switch
|
||||
public static ResolutionScalingMode FromXIVSysConf(uint mode) => mode switch
|
||||
{
|
||||
0 => ResolutionScalingMode.FSR,
|
||||
1 => ResolutionScalingMode.DLSS,
|
||||
_ => ResolutionScalingMode.Linear
|
||||
};
|
||||
|
||||
public static uint ToXIVSysConf(this ResolutionScalingMode mode) => mode switch
|
||||
{
|
||||
ResolutionScalingMode.FSR => 0,
|
||||
ResolutionScalingMode.DLSS => 1,
|
||||
_ => 0
|
||||
};
|
||||
|
||||
public static ResolutionScalingMode FromXIVGFX(byte mode) => mode switch
|
||||
{
|
||||
0 => ResolutionScalingMode.Linear,
|
||||
1 => ResolutionScalingMode.FSR,
|
||||
2 => ResolutionScalingMode.DLSS,
|
||||
_ => ResolutionScalingMode.Linear
|
||||
};
|
||||
|
||||
public static byte ToXIVGFX(this ResolutionScalingMode mode) => mode switch
|
||||
{
|
||||
ResolutionScalingMode.Point => 0,
|
||||
ResolutionScalingMode.Linear => 0,
|
||||
|
@ -152,5 +174,20 @@ public static class ResolutionScalingModeExt
|
|||
_ => null
|
||||
};
|
||||
|
||||
public static bool IsUnsupported(this ResolutionScalingMode mode) => mode == ResolutionScalingMode.DLSS;
|
||||
public static bool IsBroken(this ResolutionScalingMode mode) => mode switch
|
||||
{
|
||||
#if !DEBUG
|
||||
ResolutionScalingMode.DLSS => true,
|
||||
#endif
|
||||
_ => false
|
||||
};
|
||||
|
||||
public static unsafe bool IsSupported(this ResolutionScalingMode mode) => mode switch
|
||||
{
|
||||
ResolutionScalingMode.DLSS => PostEffectManagerEx.Instance()->DLSS != null,
|
||||
_ => true,
|
||||
};
|
||||
|
||||
public static ResolutionScalingMode ToSupported(this ResolutionScalingMode mode) =>
|
||||
!mode.IsSupported() ? ResolutionScalingMode.FSR : mode;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<PropertyGroup>
|
||||
<Authors>0x0ade</Authors>
|
||||
<Company></Company>
|
||||
<Version>0.4.2.0</Version>
|
||||
<Version>0.4.2.1</Version>
|
||||
<Description></Description>
|
||||
<Copyright></Copyright>
|
||||
<PackageProjectUrl></PackageProjectUrl>
|
||||
|
|
|
@ -6,6 +6,7 @@ using FFXIVClientStructs.FFXIV.Client.System.Framework;
|
|||
using FloppyUtils;
|
||||
using SharpDX;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using TerraFX.Interop.DirectX;
|
||||
|
@ -28,10 +29,13 @@ public unsafe class GameSizeState : IDisposable
|
|||
private Hook<ImmediateBindCSSRVs> _immediateBindCSSRVsHook;
|
||||
private Hook<CreateTexture2D> _createTexture2DHook;
|
||||
|
||||
private PostEffectManagerEx* _postEffectManager;
|
||||
|
||||
private SDX11.DeviceContext _d3dctx;
|
||||
private SDX11.Device _d3ddev;
|
||||
private SDX11.SamplerState _samplerMips;
|
||||
private SDX11.SamplerState _samplerPoint;
|
||||
private SDX11.SamplerState _samplerLinear;
|
||||
|
||||
private bool _wasEnabled = false;
|
||||
private object _renderLock = new();
|
||||
|
@ -40,8 +44,14 @@ public unsafe class GameSizeState : IDisposable
|
|||
|
||||
private uint _drawCount;
|
||||
|
||||
private ResolutionScalingMode? _setConfigGraphicsRezoType;
|
||||
|
||||
public GameSizeState()
|
||||
{
|
||||
var pfx = PostEffectManagerEx.Instance();
|
||||
Service.PluginLog.Debug($"PostEffectManager: 0x{(long) (nint) pfx:X16}");
|
||||
Service.PluginLog.Info($"DLSS: {(pfx->DLSS != null ? "Available" : "Unavailable")}");
|
||||
|
||||
var dev = (DeviceEx*) Device.Instance();
|
||||
_d3dctx = CppObject.FromPointer<SDX11.DeviceContext>((nint) dev->D3D11DeviceContext);
|
||||
_d3ddev = _d3dctx.Device;
|
||||
|
@ -58,6 +68,9 @@ public unsafe class GameSizeState : IDisposable
|
|||
samplerDesc.MaximumLod = 0;
|
||||
_samplerPoint = new(_d3ddev, samplerDesc);
|
||||
|
||||
samplerDesc.Filter = SDX11.Filter.MinMagLinearMipPoint;
|
||||
_samplerLinear = new(_d3ddev, samplerDesc);
|
||||
|
||||
/* Writes DynamicResolutionTargetHeight to size[1] near the end,
|
||||
* but if in (gpose || main menu), only scale < 1??
|
||||
*/
|
||||
|
@ -213,6 +226,7 @@ public unsafe class GameSizeState : IDisposable
|
|||
_createTexture2DHook.Dispose();
|
||||
lock (_renderLock)
|
||||
{
|
||||
_samplerLinear.Dispose();
|
||||
_samplerPoint.Dispose();
|
||||
_samplerMips.Dispose();
|
||||
}
|
||||
|
@ -220,15 +234,26 @@ public unsafe class GameSizeState : IDisposable
|
|||
Service.Framework.RunOnFrameworkThread(Update);
|
||||
}
|
||||
|
||||
public void SetConfigGraphicsRezoType(ResolutionScalingMode mode)
|
||||
{
|
||||
_setConfigGraphicsRezoType = mode;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
_dbg.Clear();
|
||||
|
||||
ref var cfg = ref Service.Config._.Game;
|
||||
|
||||
if (_setConfigGraphicsRezoType is { } setType)
|
||||
{
|
||||
_setConfigGraphicsRezoType = null;
|
||||
Service.GameConfig.System.Set(SystemConfigOption.GraphicsRezoUpscaleType.ToString(), setType.ToXIVSysConf());
|
||||
}
|
||||
|
||||
ConfigDynRezo = Service.GameConfig.System.GetUInt(SystemConfigOption.DynamicRezoType.ToString()) != 0U;
|
||||
// GameConfig starts with FSR at 0; GraphicsConfig starts with FSR at 1
|
||||
ConfigGraphicsRezoType = (ResolutionScalingMode) (Service.GameConfig.System.GetUInt(SystemConfigOption.GraphicsRezoUpscaleType.ToString()) + 1);
|
||||
ConfigGraphicsRezoType = ResolutionScalingModeExt.FromXIVSysConf(Service.GameConfig.System.GetUInt(SystemConfigOption.GraphicsRezoUpscaleType.ToString()));
|
||||
ConfigGraphicsRezoScale = Service.GameConfig.System.GetUInt(SystemConfigOption.GraphicsRezoScale.ToString()) / 100f;
|
||||
|
||||
var dev = (DeviceEx*) Device.Instance();
|
||||
|
@ -239,9 +264,6 @@ public unsafe class GameSizeState : IDisposable
|
|||
{
|
||||
_dbg.Append(@$"DR !{gfx->DynamicRezoEnable} +{gfx->DynamicRezoEnableBeyond1} _{gfx->DynamicRezoEnableCutScene} ?{gfx->DynamicRezoEnableUnkx47} ?{gfx->DynamicRezoEnableUnkx48}
|
||||
GR x{gfx->GraphicsRezoScale} ?{gfx->GraphicsRezoUnk1} _{gfx->GraphicsRezoUpscaleType} ?{gfx->GraphicsRezoUnk2}
|
||||
DEV 0x{(long) (nint) dev:X16}
|
||||
GFX 0x{(long) (nint) gfx:X16}
|
||||
RTM 0x{(long) (nint) rtm:X16}
|
||||
RTM {rtm->Resolution_Width} x {rtm->Resolution_Height}
|
||||
RTM H {rtm->DynamicResolutionActualTargetHeight} {rtm->DynamicResolutionTargetHeight} {rtm->DynamicResolutionMaximumHeight} {rtm->DynamicResolutionMinimumHeight}
|
||||
RTM S {rtm->GraphicsRezoScalePrev} {rtm->GraphicsRezoScaleGlassX} {rtm->GraphicsRezoScaleGlassY} {rtm->GraphicsRezoScaleGlassX} {rtm->GraphicsRezoScaleGlassY}
|
||||
|
@ -258,12 +280,12 @@ RR {dev->RequestRender} 0x{(long) dev->ImmediateContext->IfNonZeroSkipPostTickPr
|
|||
gfx->DynamicRezoEnable = (byte) (ConfigDynRezo || enabled ? 1 : 0);
|
||||
if (enabled)
|
||||
{
|
||||
gfx->GraphicsRezoUpscaleType = cfg.Scale <= 1f ? Service.Config._.ResolutionScalingMode.ToXIV() : ResolutionScalingMode.Linear.ToXIV();
|
||||
gfx->GraphicsRezoUpscaleType = cfg.Scale <= 1f ? Service.Config._.ResolutionScalingMode.ToXIVGFX() : ResolutionScalingMode.Linear.ToXIVGFX();
|
||||
rtm->DynamicResolutionMinimumHeight = rtm->DynamicResolutionMaximumHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
gfx->GraphicsRezoUpscaleType = (byte) ConfigGraphicsRezoType;
|
||||
gfx->GraphicsRezoUpscaleType = ConfigGraphicsRezoType.ToSupported().ToXIVGFX();
|
||||
}
|
||||
_wasEnabled = enabled;
|
||||
}
|
||||
|
@ -277,9 +299,10 @@ RR {dev->RequestRender} 0x{(long) dev->ImmediateContext->IfNonZeroSkipPostTickPr
|
|||
{
|
||||
if (!unloading)
|
||||
{
|
||||
Service.PluginLog.Debug($"Regenerating dirty RTM - locking ImmediateContextDX11.ProcessCommands");
|
||||
lock (_renderLock)
|
||||
{
|
||||
Service.PluginLog.Debug($"Regenerating dirty RTM - locking ImmediateContextDX11.ProcessCommands");
|
||||
Service.PluginLog.Debug($"Regenerating dirty RTM - locked ImmediateContextDX11.ProcessCommands");
|
||||
dev->RequestResolutionChange = 1;
|
||||
RTMDestroyAfterResizeDetour();
|
||||
RTMRegenAfterResizeDetour();
|
||||
|
@ -341,6 +364,8 @@ RR {dev->RequestRender} 0x{(long) dev->ImmediateContext->IfNonZeroSkipPostTickPr
|
|||
|
||||
private void RTMApplyScalingDetour(RenderTargetManagerEx* rtm, uint* size, byte unk1)
|
||||
{
|
||||
Debug.Assert(rtm == RenderTargetManager.Instance());
|
||||
|
||||
ref var cfg = ref Service.Config._.Game;
|
||||
if (Service.Plugin.Unloading || !cfg.IsEnabled)
|
||||
{
|
||||
|
@ -452,6 +477,8 @@ RR {dev->RequestRender} 0x{(long) dev->ImmediateContext->IfNonZeroSkipPostTickPr
|
|||
ImmediateContextEx* im, PixelShader* ps, ImmediateSRV* data
|
||||
)
|
||||
{
|
||||
Debug.Assert(im == Device.Instance()->ImmediateContext);
|
||||
|
||||
var rtm = (RenderTargetManagerEx*) RenderTargetManager.Instance();
|
||||
bool called = false;
|
||||
|
||||
|
@ -463,22 +490,29 @@ RR {dev->RequestRender} 0x{(long) dev->ImmediateContext->IfNonZeroSkipPostTickPr
|
|||
|
||||
Orig();
|
||||
|
||||
SDX11.SamplerState? sampler = null;
|
||||
|
||||
if (Service.Config._.Game.IsEnabled && Service.Config._.ResolutionScalingMode == ResolutionScalingMode.Point)
|
||||
{
|
||||
stage.SetSampler(0, _samplerPoint);
|
||||
if (!isPS)
|
||||
{
|
||||
_d3dctx.PixelShader.SetSampler(0, _samplerPoint);
|
||||
}
|
||||
sampler = _samplerPoint;
|
||||
}
|
||||
else if (tex->MipLevel != 1)
|
||||
{
|
||||
_d3dctx.PixelShader.SetSampler(0, _samplerMips);
|
||||
sampler = _samplerMips;
|
||||
_d3dctx.GenerateMips(CppObject.FromPointer<SDX11.ShaderResourceView>((nint) tex->D3D11ShaderResourceView));
|
||||
}
|
||||
else if (Service.Config._.Game.IsEnabled && Service.Config._.ResolutionScalingMode == ResolutionScalingMode.Linear)
|
||||
{
|
||||
sampler = _samplerLinear;
|
||||
}
|
||||
|
||||
if (sampler is not null)
|
||||
{
|
||||
stage.SetSampler(0, sampler);
|
||||
if (!isPS)
|
||||
{
|
||||
_d3dctx.PixelShader.SetSampler(0, _samplerMips);
|
||||
_d3dctx.PixelShader.SetSampler(0, sampler);
|
||||
}
|
||||
_d3dctx.GenerateMips(CppObject.FromPointer<SDX11.ShaderResourceView>((nint) tex->D3D11ShaderResourceView));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -647,3 +681,32 @@ public unsafe struct ImmediateSRV
|
|||
[FieldOffset(0x14)]
|
||||
public uint Unkx14;
|
||||
}
|
||||
|
||||
// There's currently no effort to C#-ify the PostEffectManager findings in CS.
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public unsafe struct PostEffectManagerEx
|
||||
{
|
||||
private static PostEffectManagerEx* _instance;
|
||||
|
||||
public static PostEffectManagerEx* Instance()
|
||||
{
|
||||
if (Service.SigScanner is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var code = Service.SigScanner.ScanText("48 83 EC ?? 48 8B 05 ?? ?? ?? ?? 49 8B F9 49 8B F0 4C 8B F2 48 8B 98 ?? ?? 00 00 48 85 DB");
|
||||
var found = Service.SigScanner.ResolveRelativeAddress(code + 4 + 7, *(int*) (code + 4 + 3));
|
||||
return _instance = (PostEffectManagerEx*) *(nint*) found;
|
||||
}
|
||||
|
||||
/* Identifiable by being used for DLSS initialization when the upscale type == 2,
|
||||
* and containing NVSDK NGX capability param attribs at *+0x158 since 2024?
|
||||
* The function setting it up is very similar to NVIDIA's sample code,
|
||||
* but in case of emergency, CTRL+F NVSDK_NGX_D3D11_GetCapabilityParameters (always exported?)
|
||||
* and the two magic strings "SuperSampling.NeedsUpdatedDriver" and "SuperSampling.Available"
|
||||
*/
|
||||
[FieldOffset(0x4220)]
|
||||
public void* DLSS;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using CustomResolution.Hooks;
|
||||
using Dalamud.Game;
|
||||
using Dalamud.Game.Text;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.IoC;
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Services;
|
||||
|
|
|
@ -125,7 +125,22 @@ Changed via /cres");
|
|||
|
||||
private void DrawGameTab()
|
||||
{
|
||||
using var imTab = ImRaii.TabItem($"Gameplay##GameTab");
|
||||
var unsupportedSysScale = !Service.GameSize.ConfigGraphicsRezoType.IsSupported();
|
||||
|
||||
var blinkTime = (DateTime.UtcNow.Ticks % TimeSpan.TicksPerHour) / (float) TimeSpan.TicksPerSecond;
|
||||
var blink = (blinkTime % 2) < 1;
|
||||
|
||||
if (unsupportedSysScale && blink)
|
||||
{
|
||||
ImGui.PushStyleColor(ImGuiCol.Border, 0xFF00FFFF);
|
||||
}
|
||||
|
||||
using var imTab = ImRaii.TabItem($"Gameplay{(unsupportedSysScale ? " \uE0C0" : "")}##GameTab");
|
||||
|
||||
if (unsupportedSysScale && blink)
|
||||
{
|
||||
ImGui.PopStyleColor();
|
||||
}
|
||||
|
||||
if (ImGui.IsItemHovered())
|
||||
{
|
||||
|
@ -147,6 +162,21 @@ Changed via /gres");
|
|||
return;
|
||||
}
|
||||
|
||||
if (unsupportedSysScale)
|
||||
{
|
||||
using var border = ImRaii.PushColor(ImGuiCol.Border, 0xFF00FFFF);
|
||||
if (ImGui.Button(@$"Your game system configuration is currently stuck on
|
||||
an unsupported graphics upscaling option: {Service.GameSize.ConfigGraphicsRezoType}
|
||||
|
||||
This can happen after you've replaced your GPU,
|
||||
or when your graphic driver has encountered problems.
|
||||
|
||||
Click here to reset to FSR and fix the scaling slider.##FixDLSS"))
|
||||
{
|
||||
Service.GameSize.SetConfigGraphicsRezoType(ResolutionScalingMode.FSR);
|
||||
}
|
||||
}
|
||||
|
||||
using (ImRaii.Disabled())
|
||||
{
|
||||
ImGui.InputInt2("Current size", ref _displayCurrentGameWH[0]);
|
||||
|
@ -160,7 +190,7 @@ Changed via /gres");
|
|||
{
|
||||
foreach (var mode in Enum.GetValues<ResolutionScalingMode>())
|
||||
{
|
||||
if (ImGui.Selectable(mode.ToHumanNameString(), _.ResolutionScalingMode == mode, mode.IsUnsupported() ? ImGuiSelectableFlags.Disabled : ImGuiSelectableFlags.None))
|
||||
if (ImGui.Selectable(mode.ToHumanNameString(), _.ResolutionScalingMode == mode, mode.IsBroken() ? ImGuiSelectableFlags.Disabled : ImGuiSelectableFlags.None))
|
||||
{
|
||||
_.ResolutionScalingMode = mode;
|
||||
}
|
||||
|
@ -176,11 +206,15 @@ Changed via /gres");
|
|||
|
||||
if (Service.DebugConfig.IsDebug)
|
||||
{
|
||||
if (ImGui.Button("(DEBUG) Set game config to DLSS"))
|
||||
{
|
||||
Service.GameSize.SetConfigGraphicsRezoType(ResolutionScalingMode.DLSS);
|
||||
}
|
||||
|
||||
ImGui.Text(Service.GameSize.DebugInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void DrawSizeTabShared(ref ConfigurationV1.SizeConfig size, string name, bool scaleOnly = false)
|
||||
{
|
||||
ImGui.Checkbox("Enabled", ref size.IsEnabled);
|
||||
|
@ -308,5 +342,11 @@ in case the resolution changes unexpectedly, or in case the resolution goes too
|
|||
In the absolute worst case, delete the following file to reset your settings:
|
||||
%%AppData%%\XIVLauncher\pluginConfigs\{Service.PluginName}.json");
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
var debug = Service.DebugConfig.IsDebug;
|
||||
ImGui.Checkbox("DEBUG!", ref debug);
|
||||
Service.DebugConfig.IsDebug = debug;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue