You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

171 lines
6.5 KiB

using System;
#if UNITY_STANDALONE_WIN
using AMDUP = UnityEngine.AMD;
#endif
using FidelityFX.FSR3;
namespace UnityEngine.Rendering.HighDefinition.AMD.FSR4
{
/// <summary>
/// Custom upscaler plugin that uses a native plugin to integrate FSR4 into Unity.
/// </summary>
public class FSR4UpscalerPlugin: UpscalerPlugin
{
public override string name => "FSR 4.0";
public override bool isSupported => SystemInfo.supportsComputeShaders &&
SystemInfo.operatingSystemFamily == OperatingSystemFamily.Windows &&
SystemInfo.graphicsDeviceType == GraphicsDeviceType.Direct3D12 &&
SystemInfo.graphicsDeviceName.StartsWith("AMD Radeon RX 90"); // Limited to only AMD RDNA4 cards (RX 9000 series) at the moment
public override bool includesSharpening => true;
public override bool isMLBased => true;
public override bool supportsAlpha => false;
private bool _nativePluginLoaded;
public override bool Load()
{
_nativePluginLoaded = false;
#if UNITY_STANDALONE_WIN
try
{
if (AMDUP.AMDUnityPlugin.IsLoaded() || AMDUP.AMDUnityPlugin.Load())
{
_nativePluginLoaded = AMDUP.GraphicsDevice.device != null || AMDUP.GraphicsDevice.CreateGraphicsDevice() != null;
if (_nativePluginLoaded)
return true;
}
}
catch (DllNotFoundException)
{
_nativePluginLoaded = false;
}
#endif
return _nativePluginLoaded;
}
public override bool IsLoaded() => _nativePluginLoaded;
public override UpscalerContext CreateContext(in FSR2CommandInitializationData initSettings)
{
if (_nativePluginLoaded)
{
var context = new FSR4NativeUpscalerContext(in initSettings);
context.Init();
return context;
}
return null;
}
public override void DestroyContext(UpscalerContext context)
{
switch (context)
{
case FSR4NativeUpscalerContext nativeContext:
nativeContext.Destroy();
break;
}
}
public override bool GetRenderResolutionFromQualityMode(FSR2Quality qualityMode, uint displayWidth, uint displayHeight, out uint renderWidth, out uint renderHeight)
{
Fsr3Upscaler.GetRenderResolutionFromQualityMode(out int rw, out int rh, (int)displayWidth, (int)displayHeight, (Fsr3Upscaler.QualityMode)((int)qualityMode + 2));
renderWidth = (uint)rw;
renderHeight = (uint)rh;
return true;
}
public override float GetUpscaleRatioFromQualityMode(FSR2Quality qualityMode)
{
return Fsr3Upscaler.GetUpscaleRatioFromQualityMode((Fsr3Upscaler.QualityMode)((int)qualityMode + 2));
}
}
public class FSR4NativeUpscalerContext : UpscalerContext
{
#if UNITY_STANDALONE_WIN
// We reuse the native interop from Unity's AMD module, hence the references to FSR2 here
private AMDUP.FSR2Context _nativeContext;
private readonly FSR2CommandInitializationData _initData;
internal FSR4NativeUpscalerContext(in FSR2CommandInitializationData initSettings)
{
_initData = initSettings;
}
internal void Init()
{
AMDUP.FSR2CommandInitializationData initSettings = new()
{
maxRenderSizeWidth = _initData.maxRenderSizeWidth,
maxRenderSizeHeight = _initData.maxRenderSizeHeight,
displaySizeWidth = _initData.displaySizeWidth,
displaySizeHeight = _initData.displaySizeHeight,
ffxFsrFlags = (AMDUP.FfxFsr2InitializationFlags)_initData.ffxFsrFlags,
};
CommandBuffer cmd = new();
_nativeContext = AMDUP.GraphicsDevice.device.CreateFeature(cmd, in initSettings);
Graphics.ExecuteCommandBuffer(cmd);
cmd.Release();
}
internal void Destroy()
{
if (_nativeContext == null)
return;
CommandBuffer cmd = new();
AMDUP.GraphicsDevice.device.DestroyFeature(cmd, _nativeContext);
Graphics.ExecuteCommandBuffer(cmd);
cmd.Release();
_nativeContext = null;
}
public override void Execute(CommandBuffer cmd, in FSR2CommandExecutionData executeData, in FSR2TextureTable textures)
{
ref var execData = ref _nativeContext.executeData;
execData.jitterOffsetX = executeData.jitterOffsetX;
execData.jitterOffsetY = executeData.jitterOffsetY;
execData.MVScaleX = executeData.MVScaleX;
execData.MVScaleY = executeData.MVScaleY;
execData.renderSizeWidth = executeData.renderSizeWidth;
execData.renderSizeHeight = executeData.renderSizeHeight;
execData.enableSharpening = executeData.enableSharpening;
execData.sharpness = executeData.sharpness;
execData.frameTimeDelta = executeData.frameTimeDelta;
execData.preExposure = executeData.preExposure;
execData.reset = executeData.reset;
execData.cameraNear = executeData.cameraNear;
execData.cameraFar = executeData.cameraFar;
execData.cameraFovAngleVertical = executeData.cameraFovAngleVertical;
AMDUP.FSR2TextureTable textureTable = new()
{
colorInput = textures.colorInput,
depth = textures.depth,
motionVectors = textures.motionVectors,
exposureTexture = textures.exposureTexture,
biasColorMask = textures.biasColorMask,
reactiveMask = textures.reactiveMask,
transparencyMask = textures.transparencyMask,
colorOutput = textures.colorOutput,
};
AMDUP.GraphicsDevice.device.ExecuteFSR2(cmd, _nativeContext, in textureTable);
}
#else
internal FSR4NativeUpscalerContext(in FSR2CommandInitializationData initSettings) { }
internal void Init() { }
internal void Destroy() { }
public override void Execute(CommandBuffer cmd, in FSR2CommandExecutionData executeData, in FSR2TextureTable textures) { }
#endif
}
}