#if ENABLE_UPSCALER_FRAMEWORK using System; using UnityEditor; using UnityEngine.Rendering.RenderGraphModule; namespace UnityEngine.Rendering { /// /// Selects how an upscaler's render resolution is determined. Only meaningful for upscalers that expose a quality /// mode (); upscalers without one always behave as . /// public enum UpscalerResolutionMode { /// /// The upscaler's quality preset determines a single fixed render resolution (for example a "Quality" preset, /// or a 1:1 native preset). The pipeline renders at that resolution; any pipeline-level scaling /// (render scale or dynamic resolution) is ignored for the camera. /// QualityMode, /// /// The pipeline drives the render resolution — via render scale, dynamic resolution (adaptive or forced), /// or a custom scale — and the upscaler only constrains it to the hard / /// limits it supports (no clamp at all when it has no quality /// mode). This is the "dynamic / driven" mode, as opposed to the fixed . /// CustomScaling, } /// /// How an upscaler constrains the pipeline's render resolution. This is the resolved result reported via /// — the upscaler's capabilities combined with the user-selected /// — not a user-facing setting. /// public enum UpscalerResolutionConstraint { /// /// No constraint: the pipeline drives the render resolution unconstrained (e.g. STP, spatial filters, or FSR2 in /// custom scaling, which has no hard per-quality range). /// None, /// /// Pinned: the pipeline renders exactly at and ignores /// whatever render-resolution scaling it would otherwise apply (render scale, dynamic resolution). /// Fixed, /// /// Bounded: the pipeline drives the render resolution (render scale / dynamic resolution / forced) but must clamp /// it to .. /// (the upscaler's hard limits). /// Range, } /// /// Resolution information from an upscaler for a given display resolution and quality mode. /// Used by pipelines to configure Dynamic Resolution Scaling bounds or display resolution info in UI. /// /// /// The tells the pipeline how to select the render resolution: /// /// — render exactly at ; /// the pipeline does not drive the resolution. [] /// — the pipeline drives the render resolution /// (render scale / dynamic resolution / forced) and must clamp it to .. /// (the upscaler's hard limits). [] /// — the pipeline drives the render resolution, unconstrained. /// /// public struct UpscalerResolutionInfo { /// /// Recommended render resolution for the current quality mode. /// This is the "optimal" resolution the upscaler suggests for best quality/performance balance. /// Authoritative when is . /// public Vector2Int qualityModeResolution; /// /// How the upscaler constrains the render resolution (pin / bounded range / no constraint). See /// and the type remarks. DLSS and XeSS expose per-quality min/max /// ranges (); FSR2 does not (global DRS support only). /// public UpscalerResolutionConstraint constraint; /// /// Minimum resolution when is . /// The upscaler guarantees acceptable quality down to this resolution. /// Equals otherwise. /// public Vector2Int minResolution; /// /// Maximum resolution when is . /// This is typically the upper bound before the upscaler stops providing benefit. /// Equals otherwise. /// public Vector2Int maxResolution; /// /// Advisory lower bound on the render scale (render resolution ÷ display resolution): below this the upscaler /// still works but its quality degrades (e.g. FSR2 past its recommended ~3x maximum upscale ratio, i.e. ~0.33). /// It is a resolution-independent ratio, unlike the hard / /// pixel bounds. This is never clamped to — consumers may surface an informational notice when the render /// scale falls below it, but must keep rendering at the chosen scale. Defaults to 0 meaning "no recommendation". /// public float recommendedMinScale; /// /// Creates resolution info for a fixed resolution (no DRS range). /// /// The fixed optimal resolution. /// Resolution info with = . public static UpscalerResolutionInfo Fixed(Vector2Int resolution) { return new UpscalerResolutionInfo { qualityModeResolution = resolution, constraint = UpscalerResolutionConstraint.Fixed, minResolution = resolution, maxResolution = resolution, }; } /// /// Creates resolution info for a render-resolution range the pipeline drives within (render scale / dynamic /// resolution / forced), clamped to the upscaler's hard .. limits. /// Use to expose a quality mode's [min,max] as a clamp (e.g. DLSS in Custom Scaling), or for any upscaler with a /// hard render-resolution limit. The is /// (clamped, not pinned); when equals there is effectively no range, /// so the constraint is . /// /// The minimum render resolution the upscaler supports. /// The maximum render resolution (typically the display resolution). /// Resolution info with a clamp (or when min == max). public static UpscalerResolutionInfo Range(Vector2Int min, Vector2Int max) { return new UpscalerResolutionInfo { // Not used to select the resolution (the pipeline drives it); reported as the full-quality value for UI. qualityModeResolution = max, // A degenerate range (min == max) is no real range, so the upscaler expresses no constraint. constraint = (min != max) ? UpscalerResolutionConstraint.Range : UpscalerResolutionConstraint.None, minResolution = min, maxResolution = max, }; } } /// /// Defines the essential contract for any upscaling technology. /// /// /// An upscaler instance is a shared singleton: one instance per type serves every camera and XR view. Store no /// per-camera or per-frame state on it — per-camera state belongs in , and per-frame /// inputs (options, resolutions, matrices, ...) arrive via each frame. In particular, /// read options from io.options (passed by the pipeline); the instance does not hold them. /// public interface IUpscaler : IRenderGraphRecorder { #region PROPERTIES /// /// Gets the display name of the upscaler (e.g., "FSR2"). /// string name { get; } /// /// Returns true if the upscaler uses temporal information from previous frames. /// bool isTemporal { get; } /// /// Returns true if the upscaler supports sharpening within the upscaling pass. /// bool supportsSharpening { get; } /// /// Returns true if the upscaler exposes a quality mode that can dictate the render resolution (e.g. the /// DLSS/FSR presets). When false, the upscaler has no opinion on resolution and the pipeline drives the render /// resolution (e.g. STP, spatial filters), which is equivalent to . /// bool hasQualityMode { get; } #endregion #region METHODS /// /// Calculates the pixel jitter for the current frame. /// /// The index of the current frame, used to cycle through jitter patterns. /// The ratio of output resolution to input resolution (e.g., 2.0 for 1080p → 4K). /// Outputs the calculated sub-pixel jitter vector. /// Outputs whether the jitter vector permits scaling relative to resolution. void CalculateJitter(int frameIndex, float upscaleRatio, out Vector2 jitter, out bool allowScaling); /// /// Creates a new context for this upscaler. Upscaler authors implement this to create per-camera state. /// Called by the context manager when a new camera needs upscaling or when an existing context is invalidated. /// /// The upscaler options to create the context with. /// The target display resolution. /// A new context instance, or null for spatial upscalers that don't need context. IUpscalerContext CreateContext(UpscalerOptions options, Vector2Int displayResolution); /// /// Calculates the recommended global mip bias for texture sampling during rendering. /// Temporal upscalers typically recommend a negative bias to sample finer mip levels, /// providing more detail for temporal accumulation. /// /// /// The standard formula is log2(renderWidth / displayWidth), which produces negative /// values when upscaling (e.g., -1.0 for 2x upscaling). Some upscalers recommend an additional /// offset (e.g., -1.0) for sharper results. /// When a temporal upscaler is active, the render pipeline should use this value directly, /// bypassing any TAA mip bias settings. /// The render pipelines must guarantee this method is only called when upscaling is active /// (preUpscaleResolution < postUpscaleResolution). Implementations do not need to handle /// the no-upscaling case. /// /// The render resolution before upscaling. /// The target display resolution after upscaling. /// The recommended mip bias value (typically negative when upscaling). float CalculateMipBias(Vector2Int preUpscaleResolution, Vector2Int postUpscaleResolution); /// /// Gets resolution information for this upscaler given a display resolution and options. /// Used by pipelines to configure DRS bounds or display resolution info in UI. /// /// /// DLSS and XeSS provide per-quality-mode min/max ranges via their SDK APIs. /// FSR2 provides only optimal resolution (no per-quality range). /// Spatial upscalers return the display resolution unchanged. /// /// The options parameter is provided by the framework (Upscaling.GetGlobalOptions) and enables future per-camera /// quality settings; pipelines pass the framework-resolved options (asset default today; per-camera later). /// /// Example usage: /// /// var info = upscaler.GetResolutionInfo(displayResolution, upscaling.GetGlobalOptions(upscaler)); /// if (info.constraint == UpscalerResolutionConstraint.Range) /// { /// drsSettings.minPercentage = (float)info.minResolution.x / displayResolution.x * 100f; /// drsSettings.maxPercentage = (float)info.maxResolution.x / displayResolution.x * 100f; /// } /// /// /// The target display/output resolution. /// The upscaler options to use for resolution calculation. /// Resolution info containing optimal and optional min/max resolutions. UpscalerResolutionInfo GetResolutionInfo(Vector2Int displayResolution, UpscalerOptions options); #endregion } /// /// Base class for an upscaling technology implementation. /// public abstract class AbstractUpscaler : IUpscaler { /// public abstract string name { get; } /// public abstract bool isTemporal { get; } /// public abstract bool supportsSharpening { get; } /// public virtual bool hasQualityMode => false; /// public virtual IUpscalerContext CreateContext(UpscalerOptions options, Vector2Int displayResolution) => null; /// public virtual void CalculateJitter(int frameIndex, float upscaleRatio, out Vector2 jitter, out bool allowScaling) { jitter = -STP.Jit16(frameIndex); allowScaling = false; } /// public virtual float CalculateMipBias(Vector2Int preUpscaleResolution, Vector2Int postUpscaleResolution) { // Standard formula: log2(renderRes / displayRes) // Returns negative values when upscaling (e.g., -1.0 for 2x upscaling) // Use minimum of both axes to ensure sufficient detail for non-uniform scaling // Note: Pipeline ensures this is only called when actually upscaling (preUpscale < postUpscale) float xBias = Mathf.Log((float)preUpscaleResolution.x / postUpscaleResolution.x, 2f); float yBias = Mathf.Log((float)preUpscaleResolution.y / postUpscaleResolution.y, 2f); return Mathf.Min(xBias, yBias); } /// /// /// Default implementation reports : the upscaler has no quality /// mode, so the pipeline drives the render resolution. Override in quality-mode upscalers to /// return /. /// public virtual UpscalerResolutionInfo GetResolutionInfo(Vector2Int displayResolution, UpscalerOptions options) { // No quality mode: the pipeline drives the render resolution, unconstrained. return new UpscalerResolutionInfo { qualityModeResolution = displayResolution, minResolution = displayResolution, maxResolution = displayResolution, constraint = UpscalerResolutionConstraint.None, }; } /// public virtual void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) { } } /// /// Represents a per-camera context for temporal upscalers. /// Each camera (and XR view) gets its own context to maintain separate temporal history. /// Spatial upscalers that don't need history can return null from CreateContext(). /// public interface IUpscalerContext { /// /// The display resolution this context was created for. Upscaler authors set this at creation time. /// The context manager reads it to detect resolution and options changes that require context recreation. /// Vector2Int createdForDisplayResolution { get; } /// /// The frame number when this context was last used. /// Set automatically by the context manager each frame to track when unused contexts should be cleaned up. /// int lastUsedFrame { get; set; } /// /// Checks if this context is still valid for the given options. Upscaler authors implement the validation logic. /// The context manager calls this each frame to determine if the context needs recreation. /// /// The current upscaler options to validate against. /// True if the context is still valid, false if it needs to be recreated. bool IsValidForOptions(UpscalerOptions options); /// /// Releases native resources associated with this context. Called automatically by the context manager when the /// context expires, needs recreation, or the upscaling system is disposed. /// /// The command buffer used to record cleanup commands into. The caller executes it. /// /// A command buffer is taken rather than this being a plain managed Dispose because some upscalers own native /// resources that must be released on the render thread. Implementations may record a render-thread signal here /// instead of GPU work, and the release may complete asynchronously. /// void Cleanup(CommandBuffer cmd); } /// /// Base class for plugin-based upscaler contexts (DLSS, FSR, XeSS, etc.). /// Handles common patterns: resolution tracking, type-safe validation, and cleanup. /// Plugin upscalers extend this class and implement the abstract methods. /// /// The native context type from the plugin (e.g., DLSSContext, FSR2Context). /// The options type for this upscaler (e.g., DLSSOptions, FSR2Options). public abstract class PluginUpscalerContext : IUpscalerContext where TNativeContext : class where TOptions : UpscalerOptions { /// /// The native context from the plugin. Subclasses create it lazily on first use (creation needs a CommandBuffer, /// so it can't happen in the constructor) and assign it here; the base class destroys it via /// (calling ). The lazy-creation method is the subclass's own — e.g. DLSS's /// create-once GetOrCreateNativeContext, or FSR2's EnsureNativeContext which also recreates when its /// allocation size changes. /// protected TNativeContext m_NativeContext; /// public Vector2Int createdForDisplayResolution { get; } /// public int lastUsedFrame { get; set; } /// /// Returns true if the native context has been created. /// Use this to skip building initialization settings when the context already exists. /// public bool hasNativeContext => m_NativeContext != null; /// /// Creates a new plugin upscaler context for the specified display resolution. /// Subclasses should extract and store context-creation settings (quality mode, presets) /// in their own fields for use in RecordRenderGraph. /// Per-frame settings (sharpness, etc.) should be read from io.options instead. /// /// The target display resolution. protected PluginUpscalerContext(Vector2Int displayResolution) { createdForDisplayResolution = displayResolution; } /// /// Destroys the native context using the plugin API. /// Called by the base class Cleanup() method. /// /// The command buffer to record destruction commands into. /// The native context to destroy. protected abstract void DestroyNativeContext(CommandBuffer cmd, TNativeContext context); /// /// Validates whether the current options match the options this context was created with. /// Subclasses compare tracked option values against the provided options. /// /// The current options to validate against. /// True if the context is still valid for these options. protected abstract bool ValidateOptions(TOptions options); /// public bool IsValidForOptions(UpscalerOptions options) { return options is TOptions typed && ValidateOptions(typed); } /// public void Cleanup(CommandBuffer cmd) { if (m_NativeContext != null) { DestroyNativeContext(cmd, m_NativeContext); m_NativeContext = null; } } } /// /// Defines the inputs and outputs required for an upscaling pass. /// public class UpscalingIO : ContextItem { #region DEFINITIONS /// /// Defines how motion vector values should be interpreted by the upscaler. /// Upscalers (e.g., DLSS, FSR) typically expect screen space values representing motion from the current frame to the previous frame. /// Since Render Pipelines may use different configurations (e.g., NDC), this enum specifies the domain to derive the correct scaling factor. /// public enum MotionVectorDomain { /// /// Normalized Device Coordinates: [-1, 1] for X and Y. /// NDC, /// /// Screen Space Coordinates: [-Width, Width] for X, [-Height, Height] for Y. /// ScreenSpace, } /// /// Defines the temporal direction of the motion vectors. /// public enum MotionVectorDirection { /// /// Motion points from the previous frame to the current frame. /// PreviousFrameToCurrentFrame, /// /// Motion points from the current frame to the previous frame. /// CurrentFrameToPreviousFrame } #endregion #region BACKING_FIELDS // Context private IUpscalerContext m_Context; // Texture I/O private TextureHandle m_CameraColor; private TextureHandle m_CameraDepth; private TextureHandle m_MotionVectorColor; private TextureHandle m_ExposureTexture; private Vector2Int m_PreUpscaleResolution; private Vector2Int m_MaxPreUpscaleResolution; private Vector2Int m_PreviousPreUpscaleResolution; private Vector2Int m_PostUpscaleResolution; private bool m_EnableTexArray; private bool m_InvertedDepth; private bool m_FlippedY; private bool m_FlippedX; private bool m_HdrInput; private Vector2Int m_MotionVectorTextureSize; private MotionVectorDomain m_MotionVectorDomain; private MotionVectorDirection m_MotionVectorDirection; private bool m_JitteredMotionVectors; private Texture2D[] m_BlueNoiseTextureSet; // Camera private ulong m_CameraInstanceID; private float m_NearClipPlane; private float m_FarClipPlane; private float m_FieldOfViewDegrees; private int m_NumActiveViews; private Vector3[] m_WorldSpaceCameraPositions; private Vector3[] m_PreviousWorldSpaceCameraPositions; private Vector3[] m_PreviousPreviousWorldSpaceCameraPositions; private Matrix4x4[] m_ProjectionMatrices; private Matrix4x4[] m_PreviousProjectionMatrices; private Matrix4x4[] m_PreviousPreviousProjectionMatrices; private Matrix4x4[] m_ViewMatrices; private Matrix4x4[] m_PreviousViewMatrices; private Matrix4x4[] m_PreviousPreviousViewMatrices; private float m_PreExposureValue; private HDROutputUtils.HDRDisplayInformation m_HdrDisplayInformation; // Time private bool m_ResetHistory; private int m_FrameIndex; private float m_DeltaTime; private float m_PreviousDeltaTime; // Misc private bool m_EnableMotionScaling; private DynamicResolutionType? m_DynamicResolution; #endregion #region TEXTURE_IO /// /// The input color texture to be upscaled. /// public TextureHandle cameraColor { get { return m_CameraColor; } set { m_CameraColor = value; } } /// /// The depth texture associated with the camera color. /// public TextureHandle cameraDepth { get { return m_CameraDepth; } set { m_CameraDepth = value; } } /// /// The texture containing per-pixel motion vectors. /// public TextureHandle motionVectorColor { get { return m_MotionVectorColor; } set { m_MotionVectorColor = value; } } /// /// The texture containing exposure data, typically 1x1. /// public TextureHandle exposureTexture { get { return m_ExposureTexture; } set { m_ExposureTexture = value; } } /// /// The resolution of the source image rendered this frame (the actual render size; under dynamic resolution /// this varies frame to frame). Upscalers use this as the per-frame dispatch/subrect size. /// public Vector2Int preUpscaleResolution { get { return m_PreUpscaleResolution; } set { m_PreUpscaleResolution = value; } } /// /// The maximum render resolution the source image can reach (the allocation size), set by the pipeline. Stable /// across the dynamic-resolution range, so upscalers should allocate per-camera history/native contexts at this /// size and dispatch at — this avoids per-frame reallocation when the render /// size varies. Equals when dynamic resolution is inactive. /// (Note: DLSS is an exception — its feature must be created at the SDK's recommended optimal, not this max.) /// public Vector2Int maxPreUpscaleResolution { get { return m_MaxPreUpscaleResolution; } set { m_MaxPreUpscaleResolution = value; } } /// /// The resolution of the source image from the previous frame. /// public Vector2Int previousPreUpscaleResolution { get { return m_PreviousPreUpscaleResolution; } set { m_PreviousPreUpscaleResolution = value; } } /// /// The target resolution after upscaling. /// public Vector2Int postUpscaleResolution { get { return m_PostUpscaleResolution; } set { m_PostUpscaleResolution = value; } } /// /// Indicates if texture arrays are enabled/supported for input textures. /// public bool enableTexArray { get { return m_EnableTexArray; } set { m_EnableTexArray = value; } } /// /// Indicates if the depth buffer is inverted (Near: 1.0, Far: 0.0). /// public bool invertedDepth { get { return m_InvertedDepth; } set { m_InvertedDepth = value; } } /// /// Indicates if the Y-axis is flipped (upside down). /// public bool flippedY { get { return m_FlippedY; } set { m_FlippedY = value; } } /// /// Indicates if the X-axis is flipped (right to left). /// public bool flippedX { get { return m_FlippedX; } set { m_FlippedX = value; } } /// /// Indicates if the input color texture contains HDR data. /// public bool hdrInput { get { return m_HdrInput; } set { m_HdrInput = value; } } /// /// The actual size of the motion vector texture, which may differ from the render resolution. /// public Vector2Int motionVectorTextureSize { get { return m_MotionVectorTextureSize; } set { m_MotionVectorTextureSize = value; } } /// /// Specifies the coordinate space used within the motion vector texture. /// public MotionVectorDomain motionVectorDomain { get { return m_MotionVectorDomain; } set { m_MotionVectorDomain = value; } } /// /// Specifies the temporal direction of the motion vectors. /// public MotionVectorDirection motionVectorDirection { get { return m_MotionVectorDirection; } set { m_MotionVectorDirection = value; } } /// /// Indicates if the motion vectors include the camera jitter offset. /// public bool jitteredMotionVectors { get { return m_JitteredMotionVectors; } set { m_JitteredMotionVectors = value; } } /// /// A set of blue noise textures used for dithering or other stochastic effects during upscaling. /// public Texture2D[] blueNoiseTextureSet { get { return m_BlueNoiseTextureSet; } set { m_BlueNoiseTextureSet = value; } } #endregion #region CAMERA /// /// The unique instance ID of the camera rendering this frame. /// public ulong cameraInstanceID { get { return m_CameraInstanceID; } set { m_CameraInstanceID = value; } } /// /// The distance to the near clipping plane. /// public float nearClipPlane { get { return m_NearClipPlane; } set { m_NearClipPlane = value; } } /// /// The distance to the far clipping plane. /// public float farClipPlane { get { return m_FarClipPlane; } set { m_FarClipPlane = value; } } /// /// The vertical field of view in degrees. /// public float fieldOfViewDegrees { get { return m_FieldOfViewDegrees; } set { m_FieldOfViewDegrees = value; } } /// /// The number of active views (e.g., 2 for stereo rendering). This is the authoritative per-view count: the /// per-view arrays below (positions/matrices) may be longer than this, so always iterate /// [0, numActiveViews) and never rely on array.Length. /// public int numActiveViews { get { return m_NumActiveViews; } set { m_NumActiveViews = value; } } /// /// Absolute world-space camera position per view, current frame (length: use ). /// These are always absolute, even when are camera-relative (camera translation /// stripped from the matrix, e.g. HDRP). Reconstruct an absolute view matrix by combining the two; do not assume /// the view matrix carries the world translation. /// public Vector3[] worldSpaceCameraPositions { get { return m_WorldSpaceCameraPositions; } set { m_WorldSpaceCameraPositions = value; } } /// /// The camera positions in world space for the previous frame. /// public Vector3[] previousWorldSpaceCameraPositions { get { return m_PreviousWorldSpaceCameraPositions; } set { m_PreviousWorldSpaceCameraPositions = value; } } /// /// The camera positions in world space for the frame before the previous one. /// public Vector3[] previousPreviousWorldSpaceCameraPositions { get { return m_PreviousPreviousWorldSpaceCameraPositions; } set { m_PreviousPreviousWorldSpaceCameraPositions = value; } } /// /// The projection matrices for the current frame. /// public Matrix4x4[] projectionMatrices { get { return m_ProjectionMatrices; } set { m_ProjectionMatrices = value; } } /// /// The projection matrices for the previous frame. /// public Matrix4x4[] previousProjectionMatrices { get { return m_PreviousProjectionMatrices; } set { m_PreviousProjectionMatrices = value; } } /// /// The projection matrices for the frame before the previous one. /// public Matrix4x4[] previousPreviousProjectionMatrices { get { return m_PreviousPreviousProjectionMatrices; } set { m_PreviousPreviousProjectionMatrices = value; } } /// /// View matrices per view, current frame, in the pipeline's render space — these may be CAMERA-RELATIVE (camera /// translation removed, e.g. HDRP) for precision. Use for the absolute /// camera position; do not derive world position from the view-matrix translation. Length: use /// . /// public Matrix4x4[] viewMatrices { get { return m_ViewMatrices; } set { m_ViewMatrices = value; } } /// /// The view matrices for the previous frame. /// public Matrix4x4[] previousViewMatrices { get { return m_PreviousViewMatrices; } set { m_PreviousViewMatrices = value; } } /// /// The view matrices for the frame before the previous one. /// public Matrix4x4[] previousPreviousViewMatrices { get { return m_PreviousPreviousViewMatrices; } set { m_PreviousPreviousViewMatrices = value; } } /// /// The pre-exposure value applied to the lighting accumulation buffer. /// Some implementations (e.g., HDRP) apply exposure before tonemapping. /// Upscalers (DLSS/FSR) need this value to reconstruct the current frame without ghosting artifacts, /// usually obtained via a CPU readback on the 1x1 exposure texture. /// public float preExposureValue { get { return m_PreExposureValue; } set { m_PreExposureValue = value; } } /// /// Information required to convert HDR color gamuts to SDR. /// This is used because some upscalers do not natively support specific HDR color gamuts. /// public HDROutputUtils.HDRDisplayInformation hdrDisplayInformation { get { return m_HdrDisplayInformation; } set { m_HdrDisplayInformation = value; } } #endregion #region TIME /// /// Indicates whether the upscaler history should be cleared (e.g., on camera cuts). /// public bool resetHistory { get { return m_ResetHistory; } set { m_ResetHistory = value; } } /// /// The current frame index. /// public int frameIndex { get { return m_FrameIndex; } set { m_FrameIndex = value; } } /// /// The time elapsed since the last frame. /// public float deltaTime { get { return m_DeltaTime; } set { m_DeltaTime = value; } } /// /// The time elapsed between the previous frame and the one before it. /// public float previousDeltaTime { get { return m_PreviousDeltaTime; } set { m_PreviousDeltaTime = value; } } #endregion #region MISC /// /// Indicates if motion vector scaling is enabled. /// public bool enableMotionScaling { get { return m_EnableMotionScaling; } set { m_EnableMotionScaling = value; } } /// /// The active Dynamic Resolution Scaling state for this frame, or null when DRS is inactive. /// /// null — no DRS; the render resolution is fixed this frame (fixed-ratio upscaling). /// — render targets are allocated at display resolution /// and scaled via hardware memory aliasing; history/RTHandles should be sized at . /// — the render resolution may vary frame-to-frame with the /// target allocated at the render resolution. /// /// Convenience: dynamicResolution.HasValue means DRS is active; dynamicResolution == DynamicResolutionType.Hardware /// gates display-resolution history allocation. Upscalers using native plugin-managed history (DLSS, FSR2) can ignore the distinction. /// public DynamicResolutionType? dynamicResolution { get { return m_DynamicResolution; } set { m_DynamicResolution = value; } } #endregion #region CONTEXT /// /// The per-camera context for the active upscaler. /// Populated by the pipeline before calling RecordRenderGraph(). /// Temporal upscalers read this to access their history buffers. /// Spatial upscalers that don't need context will have this set to null. /// public IUpscalerContext context { get { return m_Context; } set { m_Context = value; } } /// /// The sub-pixel jitter offset for this frame, in the same convention your /// returns. Pass it to your native upscaler's jitter-offset input /// unchanged. Values are typically in the range [-0.5, 0.5]. /// /// /// The pipeline derives this from your result and applies it to the /// projection before handing it back here. Read it in RecordRenderGraph; do not recompute jitter there. /// public Vector2 subpixelJitter { get { return m_SubpixelJitter; } set { m_SubpixelJitter = value; } } private Vector2 m_SubpixelJitter; /// /// The current upscaler options for this frame/camera. /// Populated by the pipeline before calling RecordRenderGraph(). /// Upscalers should read per-frame settings (sharpness, etc.) from this property. /// Context-creation settings (quality mode, presets) are stored in the context itself. /// /// /// This separation enables dynamic settings changes without context recreation: /// - Quality mode changes: Invalidate context via IsValidForOptions(), recreate /// - Sharpness changes: Context stays valid, read new value from io.options /// public UpscalerOptions options { get { return m_Options; } set { m_Options = value; } } private UpscalerOptions m_Options; #endregion /// public override void Reset() { context = null; subpixelJitter = Vector2.zero; options = null; cameraColor = TextureHandle.nullHandle; cameraDepth = TextureHandle.nullHandle; motionVectorColor = TextureHandle.nullHandle; exposureTexture = TextureHandle.nullHandle; preUpscaleResolution = new(); maxPreUpscaleResolution = new(); previousPreUpscaleResolution = new(); postUpscaleResolution = new(); enableTexArray = false; invertedDepth = false; flippedX = false; flippedY = false; hdrInput = false; motionVectorTextureSize = new(); motionVectorDomain = MotionVectorDomain.NDC; motionVectorDirection = MotionVectorDirection.PreviousFrameToCurrentFrame; jitteredMotionVectors = false; blueNoiseTextureSet = null; cameraInstanceID = ulong.MaxValue; nearClipPlane = 0f; farClipPlane = 0f; fieldOfViewDegrees = 0f; numActiveViews = 0; worldSpaceCameraPositions = Array.Empty(); previousWorldSpaceCameraPositions = Array.Empty(); previousPreviousWorldSpaceCameraPositions = Array.Empty(); projectionMatrices = Array.Empty(); previousProjectionMatrices = Array.Empty(); previousPreviousProjectionMatrices = Array.Empty(); viewMatrices = Array.Empty(); previousViewMatrices = Array.Empty(); previousPreviousViewMatrices = Array.Empty(); preExposureValue = 1.0f; hdrDisplayInformation = new HDROutputUtils.HDRDisplayInformation(); resetHistory = true; frameIndex = 0; deltaTime = 0f; previousDeltaTime = 0f; enableMotionScaling = false; dynamicResolution = null; } } } #endif