Development repository for FSR2 integration into Unity Post-Processing Stack V2.
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.

176 lines
7.1 KiB

using UnityEngine.Experimental.Rendering;
#if UNITY_STANDALONE_WIN
using AMDUP = UnityEngine.AMD;
#endif
namespace UnityEngine.Rendering.PostProcessing
{
internal class FSR3NativeUpscaler: Upscaler
{
#if UNITY_STANDALONE_WIN
public static bool IsSupported => LoadNativePlugin();
private static bool _nativePluginLoaded;
private AMDUP.FSR2Context _nativeContext;
private RenderTexture _tempColorInput;
private RenderTexture _tempDepthInput;
private RenderTexture _tempMotionVectorInput;
private RenderTexture _tempColorOutput;
public override void CreateContext(PostProcessRenderContext context, Upscaling config)
{
if (!LoadNativePlugin())
return;
// Initialize FSR3 Upscaler context
AMDUP.FfxFsr2InitializationFlags flags = 0;
if (context.camera.allowHDR) flags |= AMDUP.FfxFsr2InitializationFlags.EnableHighDynamicRange;
if (config.exposureSource == Upscaling.ExposureSource.Auto) flags |= AMDUP.FfxFsr2InitializationFlags.EnableAutoExposure;
if (RuntimeUtilities.IsDynamicResolutionEnabled(context.camera)) flags |= AMDUP.FfxFsr2InitializationFlags.EnableDynamicResolution;
if (SystemInfo.usesReversedZBuffer) flags |= AMDUP.FfxFsr2InitializationFlags.DepthInverted;
AMDUP.FSR2CommandInitializationData initSettings = new()
{
maxRenderSizeWidth = (uint)config.MaxRenderSize.x,
maxRenderSizeHeight = (uint)config.MaxRenderSize.y,
displaySizeWidth = (uint)config.UpscaleSize.x,
displaySizeHeight = (uint)config.UpscaleSize.y,
ffxFsrFlags = flags,
};
CommandBuffer cmd = new();
_nativeContext = AMDUP.GraphicsDevice.device.CreateFeature(cmd, in initSettings);
Graphics.ExecuteCommandBuffer(cmd);
cmd.Release();
CreateResources(context, config);
}
public override void DestroyContext()
{
base.DestroyContext();
if (_nativeContext != null)
{
CommandBuffer cmd = new();
AMDUP.GraphicsDevice.device.DestroyFeature(cmd, _nativeContext);
Graphics.ExecuteCommandBuffer(cmd);
cmd.Release();
_nativeContext = null;
}
DestroyResources();
}
public override void Render(PostProcessRenderContext context, Upscaling config)
{
if (_nativeContext == null)
return;
var camera = context.camera;
var cmd = context.command;
cmd.BeginSample("FSR 3.1");
var scaledRenderSize = config.GetScaledRenderSize(context.camera);
ref var execData = ref _nativeContext.executeData;
execData.jitterOffsetX = -config.JitterOffset.x;
execData.jitterOffsetY = -config.JitterOffset.y;
execData.MVScaleX = -(float)scaledRenderSize.x;
execData.MVScaleY = -(float)scaledRenderSize.y;
execData.renderSizeWidth = (uint)scaledRenderSize.x;
execData.renderSizeHeight = (uint)scaledRenderSize.y;
execData.enableSharpening = config.performSharpenPass ? 1 : 0;
execData.sharpness = config.sharpness;
execData.frameTimeDelta = Time.unscaledDeltaTime * 1000f;
execData.preExposure = config.preExposure;
execData.reset = config.Reset ? 1 : 0;
execData.cameraNear = camera.nearClipPlane;
execData.cameraFar = camera.farClipPlane;
execData.cameraFovAngleVertical = camera.fieldOfView * Mathf.Deg2Rad;
PrepareInputs(cmd, context, config, _tempColorInput, _tempDepthInput, _tempMotionVectorInput);
AMDUP.FSR2TextureTable textureTable = new()
{
colorInput = _tempColorInput,
depth = _tempDepthInput,
motionVectors = _tempMotionVectorInput,
exposureTexture = config.exposureSource switch
{
Upscaling.ExposureSource.Manual when config.exposure != null => config.exposure,
Upscaling.ExposureSource.Unity => context.autoExposureTexture,
_ => null
},
biasColorMask = null,
reactiveMask = null,
transparencyMask = config.transparencyAndCompositionMask,
colorOutput = _tempColorOutput,
};
if (config.autoGenerateReactiveMask || config.autoGenerateTransparencyAndComposition)
{
textureTable.biasColorMask = GenerateReactiveMask(cmd, context, config);
}
AMDUP.GraphicsDevice.device.ExecuteFSR2(cmd, _nativeContext, in textureTable);
cmd.CopyTexture(_tempColorOutput, context.destination);
cmd.EndSample("FSR 3.1");
}
private void CreateResources(PostProcessRenderContext context, Upscaling config)
{
CreateRenderTexture(ref _tempColorInput, "FSR3 Color Input", config.MaxRenderSize, context.sourceFormat, true);
CreateRenderTexture(ref _tempDepthInput, "FSR3 Depth Input", config.MaxRenderSize, GraphicsFormat.R32_SFloat, true);
CreateRenderTexture(ref _tempMotionVectorInput, "FSR3 Motion Vector Input", config.MaxRenderSize, GraphicsFormat.R16G16_SFloat, true);
CreateRenderTexture(ref _tempColorOutput, "FSR3 Color Output", config.UpscaleSize, context.sourceFormat, true);
}
private void DestroyResources()
{
DestroyRenderTexture(ref _tempColorOutput);
DestroyRenderTexture(ref _tempMotionVectorInput);
DestroyRenderTexture(ref _tempDepthInput);
DestroyRenderTexture(ref _tempColorInput);
}
private static bool LoadNativePlugin()
{
if (_nativePluginLoaded)
return true;
if (SystemInfo.operatingSystemFamily == OperatingSystemFamily.Windows && SystemInfo.graphicsDeviceType is GraphicsDeviceType.Direct3D12 or GraphicsDeviceType.Vulkan)
{
try
{
_nativePluginLoaded = AMDUP.GraphicsDevice.device != null || AMDUP.GraphicsDevice.CreateGraphicsDevice() != null;
if (_nativePluginLoaded)
return true;
}
catch (System.DllNotFoundException)
{
_nativePluginLoaded = false;
}
}
return _nativePluginLoaded;
}
#else
public static bool IsSupported => false;
public override void CreateContext(PostProcessRenderContext context, Upscaling config)
{
}
public override void Render(PostProcessRenderContext context, Upscaling config)
{
}
#endif
}
}