Browse Source

Implemented some of the plugin swapping logic, refactored some bits and added a bit of documentation.

master
Nico de Poel 2 years ago
parent
commit
b99782a22d
  1. 16
      com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/FSR2WrapperUpscaler.cs
  2. 28
      com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/FSR3Upscaler.cs
  3. 88
      com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/UpscalerPlugin.cs

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

@ -2,14 +2,24 @@
namespace UnityEngine.Rendering.HighDefinition.AMD.FSR2Wrapper namespace UnityEngine.Rendering.HighDefinition.AMD.FSR2Wrapper
{ {
/// <summary>
/// Wrapper plugin that simply forwards calls to the original Unity native plugin implementation of FSR2.
/// Use this to verify other plugins against Unity's reference implementation.
/// </summary>
public class FSR2WrapperUpscaler: UpscalerPlugin public class FSR2WrapperUpscaler: UpscalerPlugin
{ {
public override string name => "FSR 2.1";
public override bool isSupported => IsLoaded();
public override bool Load() => UnityEngine.AMD.AMDUnityPlugin.Load(); public override bool Load() => UnityEngine.AMD.AMDUnityPlugin.Load();
public override bool IsLoaded() => UnityEngine.AMD.AMDUnityPlugin.IsLoaded(); public override bool IsLoaded() => UnityEngine.AMD.AMDUnityPlugin.IsLoaded();
public override GraphicsDevice CreateGraphicsDevice() => new FSR2WrappedGraphicsDevice(UnityEngine.AMD.GraphicsDevice.CreateGraphicsDevice()); public override GraphicsDevice CreateGraphicsDevice() => new FSR2WrappedGraphicsDevice(UnityEngine.AMD.GraphicsDevice.CreateGraphicsDevice());
public override void DestroyGraphicsDevice() { } // Noop, native plugin does not allow clearing the graphics device
public override GraphicsDevice device => new FSR2WrappedGraphicsDevice(UnityEngine.AMD.GraphicsDevice.device); public override GraphicsDevice device => new FSR2WrappedGraphicsDevice(UnityEngine.AMD.GraphicsDevice.device);
public override uint version => UnityEngine.AMD.GraphicsDevice.version; public override uint version => UnityEngine.AMD.GraphicsDevice.version;
@ -44,14 +54,12 @@ namespace UnityEngine.Rendering.HighDefinition.AMD.FSR2Wrapper
public override bool GetRenderResolutionFromQualityMode(FSR2Quality qualityMode, uint displayWidth, uint displayHeight, out uint renderWidth, out uint renderHeight) public override bool GetRenderResolutionFromQualityMode(FSR2Quality qualityMode, uint displayWidth, uint displayHeight, out uint renderWidth, out uint renderHeight)
{ {
var quality = (UnityEngine.AMD.FSR2Quality)Math.Max(0, (int)qualityMode - 2);
return _wrappedDevice.GetRenderResolutionFromQualityMode(quality, displayWidth, displayHeight, out renderWidth, out renderHeight);
return _wrappedDevice.GetRenderResolutionFromQualityMode((UnityEngine.AMD.FSR2Quality)qualityMode, displayWidth, displayHeight, out renderWidth, out renderHeight);
} }
public override float GetUpscaleRatioFromQualityMode(FSR2Quality qualityMode) public override float GetUpscaleRatioFromQualityMode(FSR2Quality qualityMode)
{ {
var quality = (UnityEngine.AMD.FSR2Quality)Math.Max(0, (int)qualityMode - 2);
return _wrappedDevice.GetUpscaleRatioFromQualityMode(quality);
return _wrappedDevice.GetUpscaleRatioFromQualityMode((UnityEngine.AMD.FSR2Quality)qualityMode);
} }
} }

28
com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/FSR3Upscaler.cs

@ -3,10 +3,18 @@ using FidelityFX;
namespace UnityEngine.Rendering.HighDefinition.AMD.FSR3 namespace UnityEngine.Rendering.HighDefinition.AMD.FSR3
{ {
/// <summary>
/// Custom upscaler plugin that uses the open source port of FSR3 to Unity.
/// This eschews using native plugins, instead using portable code that will work on any platform that supports compute shaders.
/// </summary>
public class FSR3UpscalerPlugin: UpscalerPlugin public class FSR3UpscalerPlugin: UpscalerPlugin
{ {
private static FSR3GraphicsDevice sGraphicsDeviceInstance; private static FSR3GraphicsDevice sGraphicsDeviceInstance;
public override string name => "FSR 3.0";
public override bool isSupported => SystemInfo.supportsComputeShaders;
public override bool Load() => true; public override bool Load() => true;
public override bool IsLoaded() => true; public override bool IsLoaded() => true;
@ -31,6 +39,15 @@ namespace UnityEngine.Rendering.HighDefinition.AMD.FSR3
return null; return null;
} }
public override void DestroyGraphicsDevice()
{
if (sGraphicsDeviceInstance != null)
{
sGraphicsDeviceInstance.Shutdown();
sGraphicsDeviceInstance = null;
}
}
public override GraphicsDevice device => sGraphicsDeviceInstance; public override GraphicsDevice device => sGraphicsDeviceInstance;
} }
@ -51,19 +68,22 @@ namespace UnityEngine.Rendering.HighDefinition.AMD.FSR3
internal void Shutdown() internal void Shutdown()
{ {
foreach (var context in _contextPool)
{
context.Reset();
}
if (_assets != null) if (_assets != null)
{ {
Resources.UnloadAsset(_assets); Resources.UnloadAsset(_assets);
_assets = null; _assets = null;
} }
// TODO? destroy all FSR3 contexts on the stack
} }
public override FSR2Context CreateFeature(CommandBuffer cmd, in FSR2CommandInitializationData initSettings) public override FSR2Context CreateFeature(CommandBuffer cmd, in FSR2CommandInitializationData initSettings)
{ {
var context = _contextPool.Count != 0 ? _contextPool.Pop() : new FSR3Context(); var context = _contextPool.Count != 0 ? _contextPool.Pop() : new FSR3Context();
context.Init(initSettings, _assets); // TODO might need some way to distinguish between contexts (see featureSlot)
context.Init(initSettings, _assets);
return context; return context;
} }

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

@ -1,25 +1,105 @@
using System; using System;
using System.Collections.Generic;
// This is placed in an AMD sub-namespace, to trick HDRP into using classes from here instead of from the UnityEngine.AMD namespace.
// This allows us to intercept HDRP's upscaler calls and forward them to our own implementations, without having to modify the HDRP code itself.
namespace UnityEngine.Rendering.HighDefinition.AMD namespace UnityEngine.Rendering.HighDefinition.AMD
{ {
public static class AMDUnityPlugin public static class AMDUnityPlugin
{ {
// TODO: allow dynamic switching between plugins (including shutdown of previous plugin)
// internal static readonly UpscalerPlugin ActivePlugin = new FSR2Wrapper.FSR2WrapperUpscaler();
internal static readonly UpscalerPlugin ActivePlugin = new FSR3.FSR3UpscalerPlugin();
private static readonly List<UpscalerPlugin> AvailablePlugins = new()
{
new FSR3.FSR3UpscalerPlugin(),
new FSR2Wrapper.FSR2WrapperUpscaler(),
};
internal static UpscalerPlugin ActivePlugin = AvailablePlugins[0];
public static bool Load() => ActivePlugin.Load(); public static bool Load() => ActivePlugin.Load();
public static bool IsLoaded() => ActivePlugin.IsLoaded(); public static bool IsLoaded() => ActivePlugin.IsLoaded();
/// <summary>
/// Get the list of available upscaler plugins, as a read-only list.
/// Use this to display the available options and retrieve the index of the plugin you want to activate.
/// </summary>
public static IReadOnlyList<UpscalerPlugin> GetAvailablePlugins()
{
return AvailablePlugins.AsReadOnly();
}
/// <summary>
/// Adds an upscaler plugin to the list of available plugins.
/// If a plugin of the same type already exists in the list, then the new plugin won't be added and the index of the existing plugin will be returned instead.
/// </summary>
/// <param name="plugin">The plugin to add</param>
/// <returns>The index in the plugins list where the plugin can be found. Returns a negative number if the plugin could not be added.</returns>
public static int AddPlugin(UpscalerPlugin plugin)
{
if (plugin == null)
return -1;
// Check if we already have a plugin of the same type
var pluginType = plugin.GetType();
for (int i = 0; i < AvailablePlugins.Count; ++i)
{
if (AvailablePlugins[i].GetType() == pluginType)
return i;
}
AvailablePlugins.Add(plugin);
return AvailablePlugins.Count - 1;
}
/// <summary>
/// Sets the currently active upscaler plugin.
/// This deactivates the previously active plugin and creates a new device for the newly activated plugin.
/// If the chosen plugin is already active, then this won't do anything.
/// </summary>
/// <param name="pluginIndex">The index in the available plugin list of the upscaler plugin to activate.</param>
/// <returns>Whether the plugin was successfully changed and activated.</returns>
public static bool SetActivePlugin(int pluginIndex)
{
if (pluginIndex < 0 || pluginIndex >= AvailablePlugins.Count)
return false;
var newPlugin = AvailablePlugins[pluginIndex];
if (newPlugin == null || !newPlugin.isSupported)
return false;
if (newPlugin == ActivePlugin)
return true;
// 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?
}
ActivePlugin = newPlugin;
return true;
}
} }
public abstract class UpscalerPlugin public abstract class UpscalerPlugin
{ {
public abstract string name { get; }
public abstract bool isSupported { get; }
public abstract bool Load(); public abstract bool Load();
public abstract bool IsLoaded(); public abstract bool IsLoaded();
public abstract GraphicsDevice CreateGraphicsDevice(); public abstract GraphicsDevice CreateGraphicsDevice();
public abstract void DestroyGraphicsDevice();
public abstract GraphicsDevice device { get; } public abstract GraphicsDevice device { get; }
@ -108,8 +188,6 @@ namespace UnityEngine.Rendering.HighDefinition.AMD
public enum FSR2Quality public enum FSR2Quality
{ {
NativeAA,
UltraQuality,
Quality, Quality,
Balanced, Balanced,
Performance, Performance,

Loading…
Cancel
Save