using System; using UnityEngine.Rendering.RenderGraphModule; using System.Runtime.CompilerServices; // AggressiveInlining namespace UnityEngine.Rendering.Universal { internal sealed class UpscalerPostProcessPass : PostProcessPass { public const string k_UpscaledColorTargetName = "_CameraColorUpscaled"; Texture2D[] m_BlueNoise16LTex; bool m_IsValid; public UpscalerPostProcessPass(Texture2D[] blueNoise16LTex) { this.renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing - 1; this.profilingSampler = null; // Use default name m_BlueNoise16LTex = blueNoise16LTex; m_IsValid = m_BlueNoise16LTex != null && m_BlueNoise16LTex.Length > 0; } public override void Dispose() { m_IsValid = false; } public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) { #if ENABLE_UPSCALER_FRAMEWORK if (!m_IsValid) return; UniversalCameraData cameraData = frameData.Get(); UniversalResourceData resourceData = frameData.Get(); UniversalPostProcessingData postProcessingData = frameData.Get(); var sourceTexture = resourceData.cameraColor; var srcDesc = sourceTexture.GetDescriptor(renderGraph); // Create a context item containing upscaling inputs UpscalingIO io = frameData.Create(); io.cameraColor = sourceTexture; io.cameraDepth = resourceData.cameraDepth; io.motionVectorColor = resourceData.motionVectorColor; io.motionVectorDomain = UpscalingIO.MotionVectorDomain.NDC; io.motionVectorDirection = UpscalingIO.MotionVectorDirection.PreviousFrameToCurrentFrame; io.jitteredMotionVectors = false; // URP has no jittering in MVs // io.exposureTexture; // TODO: set exposure texture when available io.preExposureValue = 1.0f; // TODO: set if exposure value is pre-multiplied io.hdrDisplayInformation = cameraData.isHDROutputActive ? cameraData.hdrDisplayInformation : new HDROutputUtils.HDRDisplayInformation(-1, -1, -1, 160.0f); io.preUpscaleResolution = new Vector2Int( cameraData.cameraTargetDescriptor.width, cameraData.cameraTargetDescriptor.height ); io.previousPreUpscaleResolution = io.preUpscaleResolution; // URP doesn't support Dynamic Resolution Scaling (DRS). io.postUpscaleResolution = new Vector2Int(cameraData.pixelWidth, cameraData.pixelHeight); io.motionVectorTextureSize = io.preUpscaleResolution; io.enableTexArray = cameraData.xr.enabled && cameraData.xr.singlePassEnabled; MotionVectorsPersistentData motionData = null; { cameraData.camera.TryGetComponent(out var additionalCameraData); Debug.Assert(additionalCameraData != null); motionData = additionalCameraData.motionVectorsPersistentData; Debug.Assert(motionData != null); } io.cameraInstanceID = cameraData.camera.GetEntityId(); io.nearClipPlane = cameraData.camera.nearClipPlane; io.farClipPlane = cameraData.camera.farClipPlane; io.fieldOfViewDegrees = cameraData.camera.fieldOfView; io.invertedDepth = SystemInfo.usesReversedZBuffer; io.flippedY = SystemInfo.graphicsUVStartsAtTop; io.flippedX = false; io.hdrInput = Experimental.Rendering.GraphicsFormatUtility.IsHDRFormat(srcDesc.format); io.numActiveViews = cameraData.xr.enabled ? cameraData.xr.viewCount : 1; io.eyeIndex = (cameraData.xr.enabled && !cameraData.xr.singlePassEnabled) ? cameraData.xr.multipassId : 0; io.worldSpaceCameraPositions = new Vector3[io.numActiveViews]; io.previousWorldSpaceCameraPositions = new Vector3[io.numActiveViews]; io.previousPreviousWorldSpaceCameraPositions = new Vector3[io.numActiveViews]; for (int i = 0; i < io.numActiveViews; i++) { io.worldSpaceCameraPositions[i] = motionData.worldSpaceCameraPos; io.previousWorldSpaceCameraPositions[i] = motionData.previousWorldSpaceCameraPos; io.previousPreviousWorldSpaceCameraPositions[i] = motionData.previousPreviousWorldSpaceCameraPos; } io.projectionMatrices = motionData.projectionStereo; io.previousProjectionMatrices = motionData.previousProjectionStereo; io.previousPreviousProjectionMatrices = motionData.previousPreviousProjectionStereo; io.viewMatrices = motionData.viewStereo; io.previousViewMatrices = motionData.previousViewStereo; io.previousPreviousViewMatrices = motionData.previousPreviousViewStereo; io.resetHistory = cameraData.resetHistory; // TODO (Apoorva): Maybe we want to support this? // URP supports adding an offset value to the TAA frame index for testing determinism as follows: // io.frameIndex = Time.frameCount + settings.jitterFrameCountOffset; io.frameIndex = Time.frameCount; io.deltaTime = motionData.deltaTime; io.previousDeltaTime = motionData.lastDeltaTime; io.blueNoiseTextureSet = m_BlueNoise16LTex; // The motion scaling feature is only active outside of test environments. If we allowed it to run // during automated graphics tests, the results of each test run would be dependent on system // performance. #if LWRP_DEBUG_STATIC_POSTFX io.enableMotionScaling = false; #else io.enableMotionScaling = true; #endif io.enableHwDrs = false; // URP doesn't support hardware dynamic resolution scaling // Insert the active upscaler's render graph passes postProcessingData.activeUpscaler.RecordRenderGraph(renderGraph, frameData); // Update the camera resolution to reflect the upscaled size var dstDesc = io.cameraColor.GetDescriptor(renderGraph); UpdateCameraResolution(renderGraph, cameraData, new Vector2Int(dstDesc.width, dstDesc.height)); // Use the output texture of upscaling resourceData.cameraColor = io.cameraColor; #endif } private class UpdateCameraResolutionPassData { internal Vector2Int newCameraTargetSize; } // Updates render target descriptors and shader constants to reflect a new render size // This should be called immediately after the resolution changes mid-frame (typically after an upscaling operation). static internal void UpdateCameraResolution(RenderGraph renderGraph, UniversalCameraData cameraData, Vector2Int newCameraTargetSize) { // Update the camera data descriptor to reflect post-upscaled sizes cameraData.cameraTargetDescriptor.width = newCameraTargetSize.x; cameraData.cameraTargetDescriptor.height = newCameraTargetSize.y; // Update the shader constants to reflect the new camera resolution using (var builder = renderGraph.AddUnsafePass("Update Camera Resolution", out var passData)) { passData.newCameraTargetSize = newCameraTargetSize; // This pass only modifies shader constants builder.AllowGlobalStateModification(true); // Wrap constant modification into a pass to force graph execution timeline. builder.SetRenderFunc(static (UpdateCameraResolutionPassData data, UnsafeGraphContext ctx) => { ctx.cmd.SetGlobalVector( ShaderPropertyId.screenSize, new Vector4( data.newCameraTargetSize.x, data.newCameraTargetSize.y, 1.0f / data.newCameraTargetSize.x, 1.0f / data.newCameraTargetSize.y ) ); }); } } // Precomputed shader ids to same some CPU cycles (mostly affects mobile) public static class ShaderConstants { } } }