diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/Plugins.meta b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/Plugins.meta new file mode 100644 index 00000000..3b8c0ba3 --- /dev/null +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/Plugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 96584e25bbf99be49a93d4ce70a6c552 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/Plugins/Win64.meta b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/Plugins/Win64.meta new file mode 100644 index 00000000..7e6322c9 --- /dev/null +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/Plugins/Win64.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b937fff2ab187b947ac25ab544c1a803 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/Plugins/Win64/XeSSUnityPlugin.dll b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/Plugins/Win64/XeSSUnityPlugin.dll new file mode 100644 index 00000000..afd5003d Binary files /dev/null and b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/Plugins/Win64/XeSSUnityPlugin.dll differ diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/Plugins/Win64/XeSSUnityPlugin.dll.meta b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/Plugins/Win64/XeSSUnityPlugin.dll.meta new file mode 100644 index 00000000..d01dc546 --- /dev/null +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/Plugins/Win64/XeSSUnityPlugin.dll.meta @@ -0,0 +1,53 @@ +fileFormatVersion: 2 +guid: ca6858b9c6165224ab03212642e3a709 +PluginImporter: + externalObjects: {} + serializedVersion: 3 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + Any: + enabled: 0 + settings: + Exclude Editor: 0 + Exclude GameCoreScarlett: 1 + Exclude GameCoreXboxOne: 1 + Exclude Linux64: 1 + Exclude OSXUniversal: 1 + Exclude PS5: 1 + Exclude Win: 1 + Exclude Win64: 0 + Editor: + enabled: 1 + settings: + CPU: x86_64 + DefaultValueInitialized: true + OS: Windows + Linux64: + enabled: 0 + settings: + CPU: x86_64 + OSXUniversal: + enabled: 0 + settings: + CPU: None + Win: + enabled: 0 + settings: + CPU: None + Win64: + enabled: 1 + settings: + CPU: x86_64 + WindowsStoreApps: + enabled: 0 + settings: + CPU: x64 + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/Plugins/Win64/libxess.dll b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/Plugins/Win64/libxess.dll new file mode 100644 index 00000000..50b9a94e Binary files /dev/null and b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/Plugins/Win64/libxess.dll differ diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/Plugins/Win64/libxess.dll.meta b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/Plugins/Win64/libxess.dll.meta new file mode 100644 index 00000000..058320fa --- /dev/null +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/Plugins/Win64/libxess.dll.meta @@ -0,0 +1,53 @@ +fileFormatVersion: 2 +guid: 40938a287de116a4e9102883ab65398c +PluginImporter: + externalObjects: {} + serializedVersion: 3 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + Any: + enabled: 0 + settings: + Exclude Editor: 0 + Exclude GameCoreScarlett: 1 + Exclude GameCoreXboxOne: 1 + Exclude Linux64: 1 + Exclude OSXUniversal: 1 + Exclude PS5: 1 + Exclude Win: 1 + Exclude Win64: 0 + Editor: + enabled: 1 + settings: + CPU: x86_64 + DefaultValueInitialized: true + OS: Windows + Linux64: + enabled: 0 + settings: + CPU: x86_64 + OSXUniversal: + enabled: 0 + settings: + CPU: None + Win: + enabled: 0 + settings: + CPU: None + Win64: + enabled: 1 + settings: + CPU: x86_64 + WindowsStoreApps: + enabled: 0 + settings: + CPU: x64 + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/UpscalerPlugin.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/UpscalerPlugin.cs index 0f920b76..fa4ec356 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/UpscalerPlugin.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/UpscalerPlugin.cs @@ -13,6 +13,7 @@ namespace UnityEngine.Rendering.HighDefinition.AMD new FSR3.FSR3UpscalerPlugin(), #if UNITY_STANDALONE_WIN new FSR2Wrapper.FSR2WrapperUpscaler(), + new XeSS.XeSSUpscalerPlugin(), #endif }; diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/XeSSUpscalerPlugin.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/XeSSUpscalerPlugin.cs new file mode 100644 index 00000000..ee0702f3 --- /dev/null +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/XeSSUpscalerPlugin.cs @@ -0,0 +1,249 @@ +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()); + } + + 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 diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/XeSSUpscalerPlugin.cs.meta b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/XeSSUpscalerPlugin.cs.meta new file mode 100644 index 00000000..f735a111 --- /dev/null +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/Upscalers/XeSSUpscalerPlugin.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 745dd005702f8a940894a7237c62ebbf \ No newline at end of file