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.
249 lines
11 KiB
249 lines
11 KiB
using System;
|
|
using System.Runtime.InteropServices;
|
|
|
|
#if UNITY_STANDALONE_WIN
|
|
namespace UnityEngine.Rendering.HighDefinition.AMD.XeSS
|
|
{
|
|
public class XeSSUpscalerPlugin: UpscalerPlugin
|
|
{
|
|
public override string name => "XeSS 1.3";
|
|
public override bool isSupported => SystemInfo.graphicsDeviceType == GraphicsDeviceType.Direct3D12;
|
|
|
|
private XeSSLibrary.Version _version;
|
|
|
|
public override bool Load()
|
|
{
|
|
return XeSSLibrary.GetUpscalerVersion(out _version) == 0;
|
|
}
|
|
|
|
public override bool IsLoaded()
|
|
{
|
|
return _version.major != 0 && _version.minor != 0;
|
|
}
|
|
|
|
public override UpscalerContext CreateContext(in FSR2CommandInitializationData initSettings)
|
|
{
|
|
XeSSUpscalerContext context = new();
|
|
context.Init(in initSettings);
|
|
return context;
|
|
}
|
|
|
|
public override void DestroyContext(UpscalerContext context)
|
|
{
|
|
((XeSSUpscalerContext)context).Destroy();
|
|
}
|
|
|
|
public override bool GetRenderResolutionFromQualityMode(FSR2Quality qualityMode, uint displayWidth, uint displayHeight, out uint renderWidth, out uint renderHeight)
|
|
{
|
|
float ratio = GetUpscaleRatioFromQualityMode(qualityMode);
|
|
renderWidth = (uint)Mathf.RoundToInt(displayWidth / ratio);
|
|
renderHeight = (uint)Mathf.RoundToInt(displayHeight / ratio);
|
|
return true;
|
|
}
|
|
|
|
public override float GetUpscaleRatioFromQualityMode(FSR2Quality qualityMode)
|
|
{
|
|
return XeSSLibrary.ConvertQuality(qualityMode) switch
|
|
{
|
|
XeSSLibrary.QualitySetting.NativeAA => 1.0f,
|
|
XeSSLibrary.QualitySetting.UltraQualityPlus => 1.3f,
|
|
XeSSLibrary.QualitySetting.UltraQuality => 1.5f,
|
|
XeSSLibrary.QualitySetting.Quality => 1.7f,
|
|
XeSSLibrary.QualitySetting.Balanced => 2.0f,
|
|
XeSSLibrary.QualitySetting.Performance => 2.3f,
|
|
XeSSLibrary.QualitySetting.UltraPerformance => 3.0f,
|
|
_ => 1.0f,
|
|
};
|
|
}
|
|
}
|
|
|
|
public class XeSSUpscalerContext : UpscalerContext
|
|
{
|
|
private IntPtr _contextHandle = IntPtr.Zero;
|
|
|
|
private XeSSLibrary.ExecuteParams _executeParams;
|
|
private IntPtr _paramsBuffer;
|
|
|
|
internal void Init(in FSR2CommandInitializationData initSettings)
|
|
{
|
|
Vector2Int outputResolution = new Vector2Int((int)initSettings.displaySizeWidth, (int)initSettings.displaySizeHeight);
|
|
|
|
XeSSLibrary.InitFlags initFlags = XeSSLibrary.InitFlags.ResponsivePixelMask;
|
|
if (initSettings.GetFlag(FfxFsr2InitializationFlags.DepthInverted)) initFlags |= XeSSLibrary.InitFlags.InvertedDepth;
|
|
if (initSettings.GetFlag(FfxFsr2InitializationFlags.EnableDisplayResolutionMotionVectors)) initFlags |= XeSSLibrary.InitFlags.HighResMotionVectors;
|
|
if (initSettings.GetFlag(FfxFsr2InitializationFlags.EnableMotionVectorsJitterCancellation)) initFlags |= XeSSLibrary.InitFlags.JitteredMotionVectors;
|
|
if (!initSettings.GetFlag(FfxFsr2InitializationFlags.EnableHighDynamicRange)) initFlags |= XeSSLibrary.InitFlags.LDRInputColor;
|
|
if (initSettings.GetFlag(FfxFsr2InitializationFlags.EnableAutoExposure)) initFlags |= XeSSLibrary.InitFlags.EnableAutoExposure;
|
|
// TODO: use NDC velocity? I think motion vectors might be in normalized device coordinates...
|
|
|
|
_contextHandle = XeSSLibrary.CreateContext(outputResolution, XeSSLibrary.QualitySetting.Quality, initFlags);
|
|
_paramsBuffer = Marshal.AllocHGlobal(Marshal.SizeOf<XeSSLibrary.ExecuteParams>());
|
|
}
|
|
|
|
internal void Destroy()
|
|
{
|
|
if (_paramsBuffer != IntPtr.Zero)
|
|
{
|
|
Marshal.FreeHGlobal(_paramsBuffer);
|
|
_paramsBuffer = IntPtr.Zero;
|
|
}
|
|
|
|
if (_contextHandle != IntPtr.Zero)
|
|
{
|
|
XeSSLibrary.DestroyContext(_contextHandle);
|
|
_contextHandle = IntPtr.Zero;
|
|
}
|
|
}
|
|
|
|
public override void Execute(CommandBuffer cmd, in FSR2CommandExecutionData executeData, in FSR2TextureTable textures)
|
|
{
|
|
_executeParams.contextHandle = _contextHandle;
|
|
|
|
_executeParams.pColorTexture = textures.colorInput.ToNativePtr();
|
|
_executeParams.pDepthTexture = textures.depth.ToNativePtr();
|
|
_executeParams.pVelocityTexture = textures.motionVectors.ToNativePtr();
|
|
_executeParams.pExposureScaleTexture = textures.exposureTexture.ToNativePtr();
|
|
_executeParams.pResponsivePixelMaskTexture = textures.biasColorMask.ToNativePtr();
|
|
_executeParams.pOutputTexture = textures.colorOutput.ToNativePtr();
|
|
|
|
_executeParams.jitterOffsetX = executeData.jitterOffsetX;
|
|
_executeParams.jitterOffsetY = executeData.jitterOffsetY;
|
|
_executeParams.exposureScale = executeData.preExposure;
|
|
_executeParams.resetHistory = (uint)executeData.reset;
|
|
_executeParams.inputWidth = executeData.renderSizeWidth;
|
|
_executeParams.inputHeight = executeData.renderSizeHeight;
|
|
|
|
Marshal.StructureToPtr(_executeParams, _paramsBuffer, false);
|
|
|
|
cmd.IssuePluginEventAndData(XeSSLibrary.GetRenderEventAndDataFunc(), 1, _paramsBuffer);
|
|
}
|
|
}
|
|
|
|
internal static class XeSSLibrary
|
|
{
|
|
private const string DllName = "XeSSUnityPlugin";
|
|
|
|
[DllImport(DllName, CallingConvention = CallingConvention.StdCall)]
|
|
public static extern IntPtr GetRenderEventAndDataFunc();
|
|
|
|
[DllImport(DllName, CallingConvention = CallingConvention.StdCall)]
|
|
public static extern int GetUpscalerVersion(out Version version);
|
|
|
|
[DllImport(DllName, CallingConvention = CallingConvention.StdCall)]
|
|
public static extern IntPtr CreateContext(Vector2Int outputResolution, QualitySetting qualitySetting, InitFlags initFlags);
|
|
|
|
[DllImport(DllName, CallingConvention = CallingConvention.StdCall)]
|
|
public static extern void DestroyContext(IntPtr contextHandle);
|
|
|
|
public enum QualitySetting
|
|
{
|
|
UltraPerformance = 100,
|
|
Performance = 101,
|
|
Balanced = 102,
|
|
Quality = 103,
|
|
UltraQuality = 104,
|
|
UltraQualityPlus = 105,
|
|
NativeAA = 106,
|
|
}
|
|
|
|
[Flags]
|
|
public enum InitFlags
|
|
{
|
|
None = 0,
|
|
/** Use motion vectors at target resolution. */
|
|
HighResMotionVectors = 1 << 0,
|
|
/** Use inverted (increased precision) depth encoding */
|
|
InvertedDepth = 1 << 1,
|
|
/** Use exposure texture to scale input color. */
|
|
ExposureScaleTexture = 1 << 2,
|
|
/** Use responsive pixel mask texture. */
|
|
ResponsivePixelMask = 1 << 3,
|
|
/** Use velocity in NDC */
|
|
UseNDCVelocity = 1 << 4,
|
|
/** Use external descriptor heap */
|
|
ExternalDescriptorHeap = 1 << 5,
|
|
/** Disable tonemapping for input and output */
|
|
LDRInputColor = 1 << 6,
|
|
/** Remove jitter from input velocity*/
|
|
JitteredMotionVectors = 1 << 7,
|
|
/** Enable automatic exposure calculation. */
|
|
EnableAutoExposure = 1 << 8
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
|
public struct Version
|
|
{
|
|
/** A major version increment indicates a new API and potentially a
|
|
* break in functionality. */
|
|
public ushort major;
|
|
/** A minor version increment indicates incremental changes such as
|
|
* optional inputs or flags. This does not break existing functionality. */
|
|
public ushort minor;
|
|
/** A patch version increment may include performance or quality tweaks or fixes for known issues.
|
|
* There's no change in the interfaces.
|
|
* Versions beyond 90 used for development builds to change the interface for the next release.
|
|
*/
|
|
public ushort patch;
|
|
/** Reserved for future use. */
|
|
public ushort reserved;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
|
public struct ExecuteParams
|
|
{
|
|
public IntPtr contextHandle;
|
|
|
|
/** Input color texture. Must be in NON_PIXEL_SHADER_RESOURCE state.*/
|
|
public IntPtr pColorTexture;
|
|
/** Input motion vector texture. Must be in NON_PIXEL_SHADER_RESOURCE state.*/
|
|
public IntPtr pVelocityTexture;
|
|
/** Optional depth texture. Required if XESS_INIT_FLAG_HIGH_RES_MV has not been specified.
|
|
* Must be in NON_PIXEL_SHADER_RESOURCE state.*/
|
|
public IntPtr pDepthTexture;
|
|
/** Optional 1x1 exposure scale texture. Required if XESS_INIT_FLAG_EXPOSURE_TEXTURE has been
|
|
* specified. Must be in NON_PIXEL_SHADER_RESOURCE state */
|
|
public IntPtr pExposureScaleTexture;
|
|
/** Optional responsive pixel mask texture. Required if XESS_INIT_FLAG_RESPONSIVE_PIXEL_MASK
|
|
* has been specified. Must be in NON_PIXEL_SHADER_RESOURCE state */
|
|
public IntPtr pResponsivePixelMaskTexture;
|
|
/** Output texture in target resolution. Must be in UNORDERED_ACCESS state.*/
|
|
public IntPtr pOutputTexture;
|
|
|
|
/** Jitter X coordinate in the range [-0.5, 0.5]. */
|
|
public float jitterOffsetX;
|
|
/** Jitter Y coordinate in the range [-0.5, 0.5]. */
|
|
public float jitterOffsetY;
|
|
/** Optional input color scaling. Default is 1. */
|
|
public float exposureScale;
|
|
/** Resets the history accumulation in this frame. */
|
|
public uint resetHistory;
|
|
/** Input color width. */
|
|
public uint inputWidth;
|
|
/** Input color height. */
|
|
public uint inputHeight;
|
|
}
|
|
|
|
public static QualitySetting ConvertQuality(FSR2Quality quality)
|
|
{
|
|
switch (quality)
|
|
{
|
|
case FSR2Quality.Quality:
|
|
return QualitySetting.Quality;
|
|
case FSR2Quality.Balanced:
|
|
return QualitySetting.Balanced;
|
|
case FSR2Quality.Performance:
|
|
return QualitySetting.Performance;
|
|
case FSR2Quality.UltraPerformance:
|
|
return QualitySetting.UltraPerformance;
|
|
default:
|
|
return QualitySetting.NativeAA;
|
|
}
|
|
}
|
|
|
|
public static IntPtr ToNativePtr(this Texture texture)
|
|
{
|
|
return texture != null ? texture.GetNativeTexturePtr() : IntPtr.Zero;
|
|
}
|
|
}
|
|
}
|
|
#endif // UNITY_STANDALONE_WIN
|