Browse Source

Rewrote the entire upscaler plugin system so that it should be hot-swappable.

FSR2 native wrapper is still a work-in-progress but also fuck that thing.
master
Nico de Poel 2 years ago
parent
commit
20f9f5efe6
  1. 63
      com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/FSR2WrapperUpscaler.cs
  2. 146
      com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/FSR3UpscalerPlugin.cs
  3. 185
      com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/UpscalerPlugin.cs

63
com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/FSR2WrapperUpscaler.cs

@ -1,6 +1,6 @@
using System;
#if UNITY_STANDALONE_WIN
#if UNITY_STANDALONE_WIN && false
namespace UnityEngine.Rendering.HighDefinition.AMD.FSR2Wrapper
{
/// <summary>
@ -11,19 +11,40 @@ namespace UnityEngine.Rendering.HighDefinition.AMD.FSR2Wrapper
{
public override string name => "FSR 2.1";
public override bool isSupported => IsLoaded();
public override bool isSupported => UnityEngine.AMD.AMDUnityPlugin.IsLoaded();
public override bool Load() => UnityEngine.AMD.AMDUnityPlugin.Load();
public override bool IsLoaded() => UnityEngine.AMD.AMDUnityPlugin.IsLoaded();
public override bool Load()
{
if (!UnityEngine.AMD.AMDUnityPlugin.Load())
return false;
public override GraphicsDevice CreateGraphicsDevice() => new FSR2WrappedGraphicsDevice(UnityEngine.AMD.GraphicsDevice.CreateGraphicsDevice());
if (UnityEngine.AMD.GraphicsDevice.device == null)
UnityEngine.AMD.GraphicsDevice.CreateGraphicsDevice();
public override void DestroyGraphicsDevice() { } // Noop, native plugin does not allow clearing the graphics device
return UnityEngine.AMD.GraphicsDevice.device != null;
}
public override GraphicsDevice device => new FSR2WrappedGraphicsDevice(UnityEngine.AMD.GraphicsDevice.device);
public override bool IsLoaded() => UnityEngine.AMD.AMDUnityPlugin.IsLoaded() && UnityEngine.AMD.GraphicsDevice.device != null;
public override uint version => UnityEngine.AMD.GraphicsDevice.version;
public override UpscalerContext CreateContext(in FSR2CommandInitializationData initSettings)
{
throw new NotImplementedException();
}
public override void DestroyContext(UpscalerContext context)
{
throw new NotImplementedException();
}
public override bool GetRenderResolutionFromQualityMode(FSR2Quality qualityMode, uint displayWidth, uint displayHeight, out uint renderWidth, out uint renderHeight)
{
return UnityEngine.AMD.GraphicsDevice.device.GetRenderResolutionFromQualityMode((UnityEngine.AMD.FSR2Quality)qualityMode, displayWidth, displayHeight, out renderWidth, out renderHeight);
}
public override float GetUpscaleRatioFromQualityMode(FSR2Quality qualityMode)
{
return UnityEngine.AMD.GraphicsDevice.device.GetUpscaleRatioFromQualityMode((UnityEngine.AMD.FSR2Quality)qualityMode);
}
}
public class FSR2WrappedGraphicsDevice: GraphicsDevice
@ -64,22 +85,21 @@ namespace UnityEngine.Rendering.HighDefinition.AMD.FSR2Wrapper
}
}
public class FSR2WrappedContext : FSR2Context
public class FSR2WrappedContext : UpscalerContext
{
internal readonly UnityEngine.AMD.FSR2Context WrappedContext;
private FSR2CommandInitializationData _initData;
public override ref FSR2CommandInitializationData initData => ref _initData;
private FSR2CommandExecutionData _executeData;
public override ref FSR2CommandExecutionData executeData => ref _executeData;
private readonly FSR2CommandInitializationData _initData;
private UnityEngine.AMD.FSR2Context _wrappedContext;
internal FSR2WrappedContext(UnityEngine.AMD.FSR2Context wrappedContext, in FSR2CommandInitializationData initData)
internal FSR2WrappedContext(in FSR2CommandInitializationData initData)
{
WrappedContext = wrappedContext;
_initData = initData;
}
internal void Init(UnityEngine.AMD.GraphicsDevice graphicsDevice)
{
_wrappedContext = graphicsDevice.CreateFeature()
}
internal void SyncExecuteData()
{
WrappedContext.executeData.jitterOffsetX = _executeData.jitterOffsetX;
@ -97,6 +117,11 @@ namespace UnityEngine.Rendering.HighDefinition.AMD.FSR2Wrapper
WrappedContext.executeData.cameraFar = _executeData.cameraFar;
WrappedContext.executeData.cameraFovAngleVertical = _executeData.cameraFovAngleVertical;
}
public override void Execute(CommandBuffer cmd, in FSR2CommandExecutionData executeData, in FSR2TextureTable textures)
{
throw new NotImplementedException();
}
}
internal static class FSR2WrapperExtensions

146
com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/FSR3UpscalerPlugin.cs

@ -9,55 +9,13 @@ namespace UnityEngine.Rendering.HighDefinition.AMD.FSR3
/// </summary>
public class FSR3UpscalerPlugin: UpscalerPlugin
{
private static FSR3GraphicsDevice sGraphicsDeviceInstance;
private Fsr3UpscalerAssets _assets;
public override string name => "FSR 3.0";
public override bool isSupported => SystemInfo.supportsComputeShaders;
public override bool Load() => true;
public override bool IsLoaded() => true;
public override GraphicsDevice CreateGraphicsDevice()
{
if (sGraphicsDeviceInstance != null)
{
sGraphicsDeviceInstance.Shutdown();
sGraphicsDeviceInstance.Initialize();
return sGraphicsDeviceInstance;
}
var graphicsDevice = new FSR3GraphicsDevice();
if (graphicsDevice.Initialize())
{
sGraphicsDeviceInstance = graphicsDevice;
return graphicsDevice;
}
Debug.LogWarning("Failed to initialize FSR3 Graphics Device");
return null;
}
public override void DestroyGraphicsDevice()
{
if (sGraphicsDeviceInstance != null)
{
sGraphicsDeviceInstance.Shutdown();
sGraphicsDeviceInstance = null;
}
}
public override GraphicsDevice device => sGraphicsDeviceInstance;
}
public class FSR3GraphicsDevice : GraphicsDevice
{
private readonly Stack<FSR3Context> _contextPool = new();
private Fsr3UpscalerAssets _assets;
internal bool Initialize()
public override bool Load()
{
if (_assets != null)
return true;
@ -66,37 +24,18 @@ namespace UnityEngine.Rendering.HighDefinition.AMD.FSR3
return _assets != null;
}
internal void Shutdown()
{
foreach (var context in _contextPool)
{
context.Reset();
}
if (_assets != null)
{
Resources.UnloadAsset(_assets);
_assets = null;
}
}
public override bool IsLoaded() => _assets != null;
public override FSR2Context CreateFeature(CommandBuffer cmd, in FSR2CommandInitializationData initSettings)
public override UpscalerContext CreateContext(in FSR2CommandInitializationData initSettings)
{
var context = _contextPool.Count != 0 ? _contextPool.Pop() : new FSR3Context();
context.Init(initSettings, _assets);
var context = new FSR3UpscalerContext(in initSettings);
context.Init(_assets);
return context;
}
public override void DestroyFeature(CommandBuffer cmd, FSR2Context fsrContext)
public override void DestroyContext(UpscalerContext context)
{
var context = (FSR3Context)fsrContext;
context.Reset();
_contextPool.Push(context);
}
public override void ExecuteFSR2(CommandBuffer cmd, FSR2Context fsrContext, in FSR2TextureTable textures)
{
((FSR3Context)fsrContext).Draw(cmd, in textures);
((FSR3UpscalerContext)context).Destroy();
}
public override bool GetRenderResolutionFromQualityMode(FSR2Quality qualityMode, uint displayWidth, uint displayHeight, out uint renderWidth, out uint renderHeight)
@ -113,50 +52,45 @@ namespace UnityEngine.Rendering.HighDefinition.AMD.FSR3
}
}
public class FSR3Context : FSR2Context
public class FSR3UpscalerContext : UpscalerContext
{
private FSR2CommandInitializationData _initData;
public override ref FSR2CommandInitializationData initData => ref _initData;
private FSR2CommandExecutionData _executeData;
public override ref FSR2CommandExecutionData executeData => ref _executeData;
private readonly Fsr3UpscalerContext _context = new();
private readonly Fsr3Upscaler.DispatchDescription _dispatchDescription = new();
private readonly FSR2CommandInitializationData _initData;
internal void Init(in FSR2CommandInitializationData initSettings, Fsr3UpscalerAssets assets)
internal FSR3UpscalerContext(in FSR2CommandInitializationData initSettings)
{
_initData = initSettings;
}
internal void Init(Fsr3UpscalerAssets assets)
{
Fsr3Upscaler.InitializationFlags flags = Fsr3Upscaler.InitializationFlags.EnableFP16Usage;
if (initSettings.GetFlag(FfxFsr2InitializationFlags.EnableHighDynamicRange)) flags |= Fsr3Upscaler.InitializationFlags.EnableHighDynamicRange;
if (initSettings.GetFlag(FfxFsr2InitializationFlags.EnableDisplayResolutionMotionVectors)) flags |= Fsr3Upscaler.InitializationFlags.EnableDisplayResolutionMotionVectors;
if (initSettings.GetFlag(FfxFsr2InitializationFlags.EnableMotionVectorsJitterCancellation)) flags |= Fsr3Upscaler.InitializationFlags.EnableMotionVectorsJitterCancellation;
if (initSettings.GetFlag(FfxFsr2InitializationFlags.DepthInverted)) flags |= Fsr3Upscaler.InitializationFlags.EnableDepthInverted;
if (initSettings.GetFlag(FfxFsr2InitializationFlags.EnableDepthInfinite)) flags |= Fsr3Upscaler.InitializationFlags.EnableDepthInfinite;
if (initSettings.GetFlag(FfxFsr2InitializationFlags.EnableAutoExposure)) flags |= Fsr3Upscaler.InitializationFlags.EnableAutoExposure;
if (initSettings.GetFlag(FfxFsr2InitializationFlags.EnableDynamicResolution)) flags |= Fsr3Upscaler.InitializationFlags.EnableDynamicResolution;
//Debug.Log($"Initializing FSR3 with max render size: {initSettings.maxRenderSizeWidth}x{initSettings.maxRenderSizeHeight}, display size: {initSettings.displaySizeWidth}x{initSettings.displaySizeHeight}, flags: {flags}");
if (_initData.GetFlag(FfxFsr2InitializationFlags.EnableHighDynamicRange)) flags |= Fsr3Upscaler.InitializationFlags.EnableHighDynamicRange;
if (_initData.GetFlag(FfxFsr2InitializationFlags.EnableDisplayResolutionMotionVectors)) flags |= Fsr3Upscaler.InitializationFlags.EnableDisplayResolutionMotionVectors;
if (_initData.GetFlag(FfxFsr2InitializationFlags.EnableMotionVectorsJitterCancellation)) flags |= Fsr3Upscaler.InitializationFlags.EnableMotionVectorsJitterCancellation;
if (_initData.GetFlag(FfxFsr2InitializationFlags.DepthInverted)) flags |= Fsr3Upscaler.InitializationFlags.EnableDepthInverted;
if (_initData.GetFlag(FfxFsr2InitializationFlags.EnableDepthInfinite)) flags |= Fsr3Upscaler.InitializationFlags.EnableDepthInfinite;
if (_initData.GetFlag(FfxFsr2InitializationFlags.EnableAutoExposure)) flags |= Fsr3Upscaler.InitializationFlags.EnableAutoExposure;
if (_initData.GetFlag(FfxFsr2InitializationFlags.EnableDynamicResolution)) flags |= Fsr3Upscaler.InitializationFlags.EnableDynamicResolution;
Debug.Log($"Initializing FSR3 with max render size: {_initData.maxRenderSizeWidth}x{_initData.maxRenderSizeHeight}, display size: {_initData.displaySizeWidth}x{_initData.displaySizeHeight}, flags: {flags}");
_context.Create(new Fsr3Upscaler.ContextDescription
{
DisplaySize = new Vector2Int((int)initSettings.displaySizeWidth, (int)initSettings.displaySizeHeight),
MaxRenderSize = new Vector2Int((int)initSettings.maxRenderSizeWidth, (int)initSettings.maxRenderSizeHeight),
DisplaySize = new Vector2Int((int)_initData.displaySizeWidth, (int)_initData.displaySizeHeight),
MaxRenderSize = new Vector2Int((int)_initData.maxRenderSizeWidth, (int)_initData.maxRenderSizeHeight),
Flags = flags,
Shaders = assets.shaders,
});
}
internal void Reset()
internal void Destroy()
{
_context.Destroy();
_initData = new FSR2CommandInitializationData();
_executeData = new FSR2CommandExecutionData();
}
internal void Draw(CommandBuffer cmd, in FSR2TextureTable textures)
public override void Execute(CommandBuffer cmd, in FSR2CommandExecutionData executeData, in FSR2TextureTable textures)
{
_dispatchDescription.Color = new ResourceView(textures.colorInput);
_dispatchDescription.Depth = new ResourceView(textures.depth);
@ -166,18 +100,18 @@ namespace UnityEngine.Rendering.HighDefinition.AMD.FSR3
_dispatchDescription.TransparencyAndComposition = new ResourceView(textures.transparencyMask);
_dispatchDescription.Output = new ResourceView(textures.colorOutput);
_dispatchDescription.JitterOffset = new Vector2(_executeData.jitterOffsetX, _executeData.jitterOffsetY);
_dispatchDescription.MotionVectorScale = new Vector2(_executeData.MVScaleX, _executeData.MVScaleY);
_dispatchDescription.RenderSize = new Vector2Int((int)_executeData.renderSizeWidth, (int)_executeData.renderSizeHeight);
_dispatchDescription.InputResourceSize = new Vector2Int((int)_executeData.renderSizeWidth, (int)_executeData.renderSizeHeight);
_dispatchDescription.EnableSharpening = _executeData.enableSharpening != 0;
_dispatchDescription.Sharpness = _executeData.sharpness;
_dispatchDescription.FrameTimeDelta = _executeData.frameTimeDelta / 1000f;
_dispatchDescription.PreExposure = _executeData.preExposure;
_dispatchDescription.Reset = _executeData.reset != 0;
_dispatchDescription.CameraNear = _executeData.cameraNear;
_dispatchDescription.CameraFar = _executeData.cameraFar;
_dispatchDescription.CameraFovAngleVertical = _executeData.cameraFovAngleVertical;
_dispatchDescription.JitterOffset = new Vector2(executeData.jitterOffsetX, executeData.jitterOffsetY);
_dispatchDescription.MotionVectorScale = new Vector2(executeData.MVScaleX, executeData.MVScaleY);
_dispatchDescription.RenderSize = new Vector2Int((int)executeData.renderSizeWidth, (int)executeData.renderSizeHeight);
_dispatchDescription.InputResourceSize = new Vector2Int((int)executeData.renderSizeWidth, (int)executeData.renderSizeHeight);
_dispatchDescription.EnableSharpening = executeData.enableSharpening != 0;
_dispatchDescription.Sharpness = executeData.sharpness;
_dispatchDescription.FrameTimeDelta = executeData.frameTimeDelta / 1000f;
_dispatchDescription.PreExposure = executeData.preExposure;
_dispatchDescription.Reset = executeData.reset != 0;
_dispatchDescription.CameraNear = executeData.cameraNear;
_dispatchDescription.CameraFar = executeData.cameraFar;
_dispatchDescription.CameraFovAngleVertical = executeData.cameraFovAngleVertical;
_dispatchDescription.ViewSpaceToMetersFactor = 1.0f; // 1 unit is 1 meter in Unity
_context.Dispatch(_dispatchDescription, cmd);

185
com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/UpscalerPlugin.cs

@ -10,7 +10,7 @@ namespace UnityEngine.Rendering.HighDefinition.AMD
private static readonly List<UpscalerPlugin> AvailablePlugins = new()
{
new FSR3.FSR3UpscalerPlugin(),
#if UNITY_STANDALONE_WIN
#if UNITY_STANDALONE_WIN && false
new FSR2Wrapper.FSR2WrapperUpscaler(),
#endif
};
@ -19,7 +19,7 @@ namespace UnityEngine.Rendering.HighDefinition.AMD
public static bool Load() => ActivePlugin.Load();
public static bool IsLoaded() => ActivePlugin.IsLoaded();
public static bool IsLoaded() => ActivePlugin.IsLoaded() || ActivePlugin.isSupported;
/// <summary>
/// Get the list of available upscaler plugins, as a read-only list.
@ -71,70 +71,181 @@ namespace UnityEngine.Rendering.HighDefinition.AMD
if (newPlugin == ActivePlugin)
return true;
if (!newPlugin.IsLoaded() && !newPlugin.Load())
return false;
// If HDRP has previously created a graphics device, then it'll expect that to remain in place.
// Hence, make sure we automatically create a graphics device for the new plugin.
if (ActivePlugin != null && ActivePlugin.device != null)
{
var newDevice = newPlugin.CreateGraphicsDevice();
if (newDevice == null)
return false;
ActivePlugin.DestroyGraphicsDevice();
// TODO do we need to create a new "Feature" as well? Does HDRP cache this anywhere?
}
// Hot-swap the upscaler contexts, so HDRP can keep calling the same FSR2Contexts without knowing the underlying implementation has changed.
GraphicsDevice.device.RecreateFeatures(ActivePlugin, newPlugin);
ActivePlugin = newPlugin;
return true;
}
}
public abstract class UpscalerPlugin
public class GraphicsDevice
{
public abstract string name { get; }
public abstract bool isSupported { get; }
public abstract bool Load();
private static GraphicsDevice sGraphicsDevice = null;
public abstract bool IsLoaded();
public abstract GraphicsDevice CreateGraphicsDevice();
public static GraphicsDevice device => sGraphicsDevice;
public abstract void DestroyGraphicsDevice();
public static uint version => 0x00;
public abstract GraphicsDevice device { get; }
private readonly HashSet<FSR2Context> _contexts = new();
public static GraphicsDevice CreateGraphicsDevice()
{
// Lazy initialization of the plugin, because HDRP fails to call AMDUnityPlugin.Load() itself
UpscalerPlugin plugin = AMDUnityPlugin.ActivePlugin;
if (plugin != null && !plugin.IsLoaded())
{
if (!plugin.Load())
{
Debug.LogWarning("Failed to initialize upscaler plugin");
return null;
}
}
if (sGraphicsDevice != null)
{
sGraphicsDevice.Shutdown();
sGraphicsDevice.Initialize();
return sGraphicsDevice;
}
GraphicsDevice graphicsDevice = new GraphicsDevice();
if (graphicsDevice.Initialize())
{
sGraphicsDevice = graphicsDevice;
return graphicsDevice;
}
Debug.LogWarning("Failed to initialize upscaler GraphicsDevice");
return null;
}
private bool Initialize()
{
return true;
}
private void Shutdown()
{
}
public virtual uint version => 0x00;
internal void RecreateFeatures(UpscalerPlugin oldPlugin, UpscalerPlugin newPlugin)
{
foreach (FSR2Context context in _contexts)
{
context.Destroy(oldPlugin);
context.Create(newPlugin);
}
}
public FSR2Context CreateFeature(CommandBuffer cmd, in FSR2CommandInitializationData initSettings)
{
FSR2Context context = new FSR2Context(in initSettings);
if (!context.Create(AMDUnityPlugin.ActivePlugin))
return null;
_contexts.Add(context);
return context;
}
public void DestroyFeature(CommandBuffer cmd, FSR2Context fsrContext)
{
fsrContext.Destroy(AMDUnityPlugin.ActivePlugin);
_contexts.Remove(fsrContext);
}
public void ExecuteFSR2(CommandBuffer cmd, FSR2Context fsrContext, in FSR2TextureTable textures)
{
fsrContext.Execute(cmd, textures);
}
public bool GetRenderResolutionFromQualityMode(FSR2Quality qualityMode, uint displayWidth, uint displayHeight, out uint renderWidth, out uint renderHeight)
{
UpscalerPlugin plugin = AMDUnityPlugin.ActivePlugin;
if (plugin == null)
{
renderWidth = displayWidth;
renderHeight = displayHeight;
return false;
}
return plugin.GetRenderResolutionFromQualityMode(qualityMode, displayWidth, displayHeight, out renderWidth, out renderHeight);
}
public float GetUpscaleRatioFromQualityMode(FSR2Quality qualityMode)
{
UpscalerPlugin plugin = AMDUnityPlugin.ActivePlugin;
if (plugin == null)
{
return 1.0f;
}
return plugin.GetUpscaleRatioFromQualityMode(qualityMode);
}
}
public abstract class GraphicsDevice
public class FSR2Context
{
public static GraphicsDevice device => AMDUnityPlugin.ActivePlugin.device;
private UpscalerContext _wrappedContext;
public static uint version => AMDUnityPlugin.ActivePlugin.version;
private FSR2CommandInitializationData _initData;
public ref FSR2CommandInitializationData initData => ref _initData;
public static GraphicsDevice CreateGraphicsDevice()
private FSR2CommandExecutionData _executeData;
public ref FSR2CommandExecutionData executeData => ref _executeData;
public FSR2Context(in FSR2CommandInitializationData initSettings)
{
return AMDUnityPlugin.ActivePlugin.CreateGraphicsDevice();
_initData = initSettings;
}
public bool Create(UpscalerPlugin plugin)
{
_wrappedContext = plugin?.CreateContext(in _initData);
return _wrappedContext != null;
}
public void Destroy(UpscalerPlugin plugin)
{
if (_wrappedContext == null)
return;
plugin?.DestroyContext(_wrappedContext);
_wrappedContext = null;
}
public abstract FSR2Context CreateFeature(CommandBuffer cmd, in FSR2CommandInitializationData initSettings);
public void Execute(CommandBuffer cmd, in FSR2TextureTable textures)
{
_wrappedContext?.Execute(cmd, in executeData, in textures);
}
}
public abstract class UpscalerPlugin
{
public abstract string name { get; }
public abstract bool isSupported { get; }
public abstract bool Load();
public abstract void DestroyFeature(CommandBuffer cmd, FSR2Context fsrContext);
public abstract bool IsLoaded();
public abstract void ExecuteFSR2(CommandBuffer cmd, FSR2Context fsrContext, in FSR2TextureTable textures);
public abstract UpscalerContext CreateContext(in FSR2CommandInitializationData initSettings);
public abstract void DestroyContext(UpscalerContext context);
public abstract bool GetRenderResolutionFromQualityMode(FSR2Quality qualityMode, uint displayWidth, uint displayHeight, out uint renderWidth, out uint renderHeight);
public abstract float GetUpscaleRatioFromQualityMode(FSR2Quality qualityMode);
}
public abstract class FSR2Context
public abstract class UpscalerContext
{
public abstract ref FSR2CommandInitializationData initData { get; }
public abstract ref FSR2CommandExecutionData executeData { get; }
public abstract void Execute(CommandBuffer cmd, in FSR2CommandExecutionData executeData, in FSR2TextureTable textures);
}
public struct FSR2CommandInitializationData

Loading…
Cancel
Save