using System; using System.Runtime.InteropServices; using UnityEngine; using UnityEngine.Rendering; namespace FidelityFX { public static class Fsr2 { // Allow overriding of certain Unity resource management behaviors by the programmer public static Fsr2Callbacks GlobalCallbacks { get; set; } = new Fsr2Callbacks(); /// /// Creates a new FSR2 context with standard parameters that are appropriate for the current platform. /// public static Fsr2Context CreateContext(Vector2Int displaySize, Vector2Int maxRenderSize, InitializationFlags flags = 0) { if (SystemInfo.usesReversedZBuffer) flags |= InitializationFlags.EnableDepthInverted; else flags &= ~InitializationFlags.EnableDepthInverted; var contextDescription = new ContextDescription { Flags = flags, DisplaySize = displaySize, MaxRenderSize = maxRenderSize, Callbacks = GlobalCallbacks, }; var context = new Fsr2Context(); context.Create(contextDescription); return context; } public static float GetUpscaleRatioFromQualityMode(QualityMode qualityMode) { switch (qualityMode) { case QualityMode.Quality: return 1.5f; case QualityMode.Balanced: return 1.7f; case QualityMode.Performance: return 2.0f; case QualityMode.UltraPerformance: return 3.0f; default: return 1.0f; } } public static void GetRenderResolutionFromQualityMode( out uint renderWidth, out uint renderHeight, int displayWidth, int displayHeight, QualityMode qualityMode) { float ratio = GetUpscaleRatioFromQualityMode(qualityMode); renderWidth = (uint)(displayWidth / ratio); renderHeight = (uint)(displayHeight / ratio); } public static int GetJitterPhaseCount(int renderWidth, int displayWidth) { const float basePhaseCount = 8.0f; int jitterPhaseCount = (int)(basePhaseCount * Mathf.Pow((float)displayWidth / renderWidth, 2.0f)); return jitterPhaseCount; } public static void GetJitterOffset(out float outX, out float outY, int index, int phaseCount) { outX = Halton((index % phaseCount) + 1, 2) - 0.5f; outY = Halton((index % phaseCount) + 1, 3) - 0.5f; } // Calculate halton number for index and base. private static float Halton(int index, int @base) { float f = 1.0f, result = 0.0f; for (int currentIndex = index; currentIndex > 0;) { f /= @base; result += f * (currentIndex % @base); currentIndex = (int)Mathf.Floor((float)currentIndex / @base); } return result; } public static float Lanczos2(float value) { return Mathf.Abs(value) < Mathf.Epsilon ? 1.0f : Mathf.Sin(Mathf.PI * value) / (Mathf.PI * value) * (Mathf.Sin(0.5f * Mathf.PI * value) / (0.5f * Mathf.PI * value)); } public enum QualityMode { Quality = 1, Balanced = 2, Performance = 3, UltraPerformance = 4, } [Flags] public enum InitializationFlags { EnableHighDynamicRange = 1 << 0, EnableDisplayResolutionMotionVectors = 1 << 1, EnableMotionVectorsJitterCancellation = 1 << 2, EnableDepthInverted = 1 << 3, EnableDepthInfinite = 1 << 4, EnableAutoExposure = 1 << 5, EnableDynamicResolution = 1 << 6, EnableTexture1DUsage = 1 << 7, EnableDebugChecking = 1 << 8, } public enum MessageType { Error = 0, Warning = 1, } public struct ContextDescription { public InitializationFlags Flags; public Vector2Int MaxRenderSize; public Vector2Int DisplaySize; public Fsr2Callbacks Callbacks; } public class DispatchDescription { // Texture2D Color, Depth, MotionVectors; // Will be passed using ComputeShader.SetTextureFromGlobal public Texture2D Exposure; public Texture2D Reactive; public Texture2D TransparencyAndComposition; public RenderTexture Input; public RenderTexture Output; public Vector2 JitterOffset; public Vector2 MotionVectorScale; public Vector2Int RenderSize; public bool EnableSharpening; public float Sharpness; public float FrameTimeDelta; public float PreExposure; public bool Reset; public float CameraNear; public float CameraFar; public float CameraFovAngleVertical; public float ViewSpaceToMetersFactor; } [Serializable, StructLayout(LayoutKind.Sequential)] internal struct Fsr2Constants { public Vector2Int renderSize; public Vector2Int maxRenderSize; public Vector2Int displaySize; public Vector2Int inputColorResourceDimensions; public Vector2Int lumaMipDimensions; public int lumaMipLevelToUse; public int frameIndex; public Vector4 deviceToViewDepth; public Vector2 jitterOffset; public Vector2 motionVectorScale; public Vector2 downscaleFactor; public Vector2 motionVectorJitterCancellation; public float preExposure; public float previousFramePreExposure; public float tanHalfFOV; public float jitterPhaseCount; public float deltaTime; public float dynamicResChangeFactor; public float viewSpaceToMetersFactor; } [Serializable, StructLayout(LayoutKind.Sequential)] internal struct SpdConstants { public uint mips; public uint numWorkGroups; public uint workGroupOffsetX, workGroupOffsetY; public uint renderSizeX, renderSizeY; } [Serializable, StructLayout(LayoutKind.Sequential)] internal struct GenerateReactiveConstants { public float scale; public float threshold; public float binaryValue; public uint flags; } [Serializable, StructLayout(LayoutKind.Sequential)] internal struct RcasConstants { public RcasConstants(uint sharpness, uint halfSharp) { this.sharpness = sharpness; this.halfSharp = halfSharp; dummy0 = dummy1 = 0; } public readonly uint sharpness; public readonly uint halfSharp; public readonly uint dummy0; public readonly uint dummy1; } } }