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
{
/// <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 override string name => "FSR 2.1";
public override bool isSupported => IsLoaded();
public override bool Load() => UnityEngine.AMD.AMDUnityPlugin.Load();
public override bool IsLoaded() => UnityEngine.AMD.AMDUnityPlugin.IsLoaded();
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 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)
{
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)
{
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
{
/// <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
{
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 IsLoaded() => true;
@ -31,6 +39,15 @@ namespace UnityEngine.Rendering.HighDefinition.AMD.FSR3
return null;
}
public override void DestroyGraphicsDevice()
{
if (sGraphicsDeviceInstance != null)
{
sGraphicsDeviceInstance.Shutdown();
sGraphicsDeviceInstance = null;
}
}
public override GraphicsDevice device => sGraphicsDeviceInstance;
}
@ -51,19 +68,22 @@ namespace UnityEngine.Rendering.HighDefinition.AMD.FSR3
internal void Shutdown()
{
foreach (var context in _contextPool)
{
context.Reset();
}
if (_assets != null)
{
Resources.UnloadAsset(_assets);
_assets = null;
}
// TODO? destroy all FSR3 contexts on the stack
}
public override FSR2Context CreateFeature(CommandBuffer cmd, in FSR2CommandInitializationData initSettings)
{
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;
}

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

@ -1,25 +1,105 @@
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
{
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 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 string name { get; }
public abstract bool isSupported { get; }
public abstract bool Load();
public abstract bool IsLoaded();
public abstract GraphicsDevice CreateGraphicsDevice();
public abstract void DestroyGraphicsDevice();
public abstract GraphicsDevice device { get; }
@ -108,8 +188,6 @@ namespace UnityEngine.Rendering.HighDefinition.AMD
public enum FSR2Quality
{
NativeAA,
UltraQuality,
Quality,
Balanced,
Performance,

Loading…
Cancel
Save