Browse Source
- Updated FSR3 Upscaler to version 3.1.3, including improvements to color clamp to help with ghosting streaks and addition of velocity factor parameter.
- Updated FSR3 Upscaler to version 3.1.3, including improvements to color clamp to help with ghosting streaks and addition of velocity factor parameter.
- Updated FSR2 to version 2.3.2, including some fixes backported from FSR3 Upscaler. - Reworked PPV2 integration to allow switching between different upscalers via a flexible plugin system. - Reduced number of SPD mip levels used by FSR3 luma pyramid and shading change pyramid passes for OpenGL Core, to ensure they stay within the limit of 8 UAV bindings. - Fixed multiple FSR2 auto-exposure issues with OpenGL Core on Nvidia GPUs, that were causing artifacting and black screen flashes. - Reorganized profiler sampling to work around issues in non-development builds on Unity 2020.x - Optimized multi-compile keywords to reduce the number of shader variants.master ppv2-3.4.0d-fsr3.1
52 changed files with 1795 additions and 463 deletions
-
23Assets/FSR2 Assets.asset
-
8Assets/FSR2 Assets.asset.meta
-
4Assets/Scripts/Fsr3UpscalerImageEffect.cs
-
12Packages/com.unity.postprocessing/PostProcessing/Editor/PostProcessLayerEditor.cs
-
11Packages/com.unity.postprocessing/PostProcessing/PostProcessResources.asset
-
2Packages/com.unity.postprocessing/PostProcessing/Runtime/Effects/DepthOfField.cs
-
341Packages/com.unity.postprocessing/PostProcessing/Runtime/Effects/SuperResolution.cs
-
312Packages/com.unity.postprocessing/PostProcessing/Runtime/Effects/Upscaling.cs
-
3Packages/com.unity.postprocessing/PostProcessing/Runtime/Effects/Upscaling.cs.meta
-
3Packages/com.unity.postprocessing/PostProcessing/Runtime/Effects/Upscaling.meta
-
124Packages/com.unity.postprocessing/PostProcessing/Runtime/Effects/Upscaling/FSR2Upscaler.cs
-
2Packages/com.unity.postprocessing/PostProcessing/Runtime/Effects/Upscaling/FSR2Upscaler.cs.meta
-
125Packages/com.unity.postprocessing/PostProcessing/Runtime/Effects/Upscaling/FSR3Upscaler.cs
-
11Packages/com.unity.postprocessing/PostProcessing/Runtime/Effects/Upscaling/FSR3Upscaler.cs.meta
-
13Packages/com.unity.postprocessing/PostProcessing/Runtime/Effects/Upscaling/Upscaler.cs
-
3Packages/com.unity.postprocessing/PostProcessing/Runtime/Effects/Upscaling/Upscaler.cs.meta
-
26Packages/com.unity.postprocessing/PostProcessing/Runtime/PostProcessLayer.cs
-
6Packages/com.unity.postprocessing/PostProcessing/Runtime/PostProcessRenderContext.cs
-
8Packages/com.unity.postprocessing/PostProcessing/Runtime/PostProcessResources.cs
-
2Packages/com.unity.postprocessing/package.json
-
2Packages/fidelityfx.fsr/Runtime/FSR2/Fsr2Context.cs
-
25Packages/fidelityfx.fsr/Runtime/FSR2/Fsr2Pass.cs
-
3Packages/fidelityfx.fsr/Runtime/FSR3/Fsr3Upscaler.cs
-
5Packages/fidelityfx.fsr/Runtime/FSR3/Fsr3UpscalerContext.cs
-
25Packages/fidelityfx.fsr/Runtime/FSR3/Fsr3UpscalerPass.cs
-
1Packages/fidelityfx.fsr/Shaders/ffx_fsr2_accumulate_pass.compute
-
3Packages/fidelityfx.fsr/Shaders/ffx_fsr2_autogen_reactive_pass.compute
-
3Packages/fidelityfx.fsr/Shaders/ffx_fsr2_compute_luminance_pyramid_pass.compute
-
2Packages/fidelityfx.fsr/Shaders/ffx_fsr2_lock_pass.compute
-
4Packages/fidelityfx.fsr/Shaders/ffx_fsr2_rcas_pass.compute
-
2Packages/fidelityfx.fsr/Shaders/ffx_fsr2_tcr_autogen_pass.compute
-
1Packages/fidelityfx.fsr/Shaders/ffx_fsr3upscaler_accumulate_pass.compute
-
5Packages/fidelityfx.fsr/Shaders/ffx_fsr_unity_common.cginc
-
4Packages/fidelityfx.fsr/Shaders/shaders/ffx_fsr3upscaler_luma_pyramid_pass.hlsl
-
2Packages/fidelityfx.fsr/Shaders/shaders/ffx_fsr3upscaler_shading_change_pyramid_pass.hlsl
-
29Packages/fidelityfx.fsr/Shaders/shaders/fsr2/ffx_fsr2_callbacks_hlsl.h
-
28Packages/fidelityfx.fsr/Shaders/shaders/fsr2/ffx_fsr2_common.h
-
1Packages/fidelityfx.fsr/Shaders/shaders/fsr2/ffx_fsr2_compute_luminance_pyramid.h
-
75Packages/fidelityfx.fsr/Shaders/shaders/fsr2/ffx_fsr2_rcas.h
-
65Packages/fidelityfx.fsr/Shaders/shaders/fsr2/ffx_fsr2_sample.h
-
283Packages/fidelityfx.fsr/Shaders/shaders/fsr2/ffx_fsr2_upsample.h
-
23Packages/fidelityfx.fsr/Shaders/shaders/fsr3upscaler/ffx_fsr3upscaler_accumulate.h
-
23Packages/fidelityfx.fsr/Shaders/shaders/fsr3upscaler/ffx_fsr3upscaler_callbacks_hlsl.h
-
2Packages/fidelityfx.fsr/Shaders/shaders/fsr3upscaler/ffx_fsr3upscaler_common.h
-
10Packages/fidelityfx.fsr/Shaders/shaders/fsr3upscaler/ffx_fsr3upscaler_luma_pyramid.h
-
77Packages/fidelityfx.fsr/Shaders/shaders/fsr3upscaler/ffx_fsr3upscaler_rcas.h
-
15Packages/fidelityfx.fsr/Shaders/shaders/fsr3upscaler/ffx_fsr3upscaler_reproject.h
-
26Packages/fidelityfx.fsr/Shaders/shaders/fsr3upscaler/ffx_fsr3upscaler_sample.h
-
8Packages/fidelityfx.fsr/Shaders/shaders/fsr3upscaler/ffx_fsr3upscaler_shading_change_pyramid.h
-
460Packages/fidelityfx.fsr/Shaders/shaders/fsr3upscaler/ffx_fsr3upscaler_upsample.h
-
2Packages/fidelityfx.fsr/package.json
-
3README.md
@ -0,0 +1,23 @@ |
|||||
|
%YAML 1.1 |
||||
|
%TAG !u! tag:unity3d.com,2011: |
||||
|
--- !u!114 &11400000 |
||||
|
MonoBehaviour: |
||||
|
m_ObjectHideFlags: 0 |
||||
|
m_CorrespondingSourceObject: {fileID: 0} |
||||
|
m_PrefabInstance: {fileID: 0} |
||||
|
m_PrefabAsset: {fileID: 0} |
||||
|
m_GameObject: {fileID: 0} |
||||
|
m_Enabled: 1 |
||||
|
m_EditorHideFlags: 0 |
||||
|
m_Script: {fileID: 11500000, guid: db26e15a33db6ab42a38daab0ba2712f, type: 3} |
||||
|
m_Name: FSR2 Assets |
||||
|
m_EditorClassIdentifier: |
||||
|
shaders: |
||||
|
computeLuminancePyramidPass: {fileID: 7200000, guid: 04c3480675e29a340808141e68d4cc8b, type: 3} |
||||
|
reconstructPreviousDepthPass: {fileID: 7200000, guid: 5060dfafe45aa67459629186ceb7464e, type: 3} |
||||
|
depthClipPass: {fileID: 7200000, guid: b207de122e2c4b844b89dcd7c5c77c80, type: 3} |
||||
|
lockPass: {fileID: 7200000, guid: 20b7864a7e7258946aaf0f1996febad3, type: 3} |
||||
|
accumulatePass: {fileID: 7200000, guid: 7e791d69a5be98247a93b63897bc64df, type: 3} |
||||
|
sharpenPass: {fileID: 7200000, guid: 40815651f0f5d994cb73da9816a7ff9b, type: 3} |
||||
|
autoGenReactivePass: {fileID: 7200000, guid: 67ee1b32ca5e4234db9f06984c783dee, type: 3} |
||||
|
tcrAutoGenPass: {fileID: 7200000, guid: f8b1c27fb6a544b43b38903592240500, type: 3} |
||||
@ -0,0 +1,8 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 0c417b61f173a764895d57dfcd7613bf |
||||
|
NativeFormatImporter: |
||||
|
externalObjects: {} |
||||
|
mainObjectFileID: 11400000 |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -1,341 +0,0 @@ |
|||||
// Copyright (c) 2024 Nico de Poel
|
|
||||
//
|
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||
// in the Software without restriction, including without limitation the rights
|
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||
// furnished to do so, subject to the following conditions:
|
|
||||
//
|
|
||||
// The above copyright notice and this permission notice shall be included in all
|
|
||||
// copies or substantial portions of the Software.
|
|
||||
//
|
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||
// THE SOFTWARE.
|
|
||||
|
|
||||
using System; |
|
||||
using System.Collections; |
|
||||
using System.Collections.Generic; |
|
||||
using UnityEngine; |
|
||||
using UnityEngine.Experimental.Rendering; |
|
||||
using FidelityFX; |
|
||||
using FidelityFX.FSR3; |
|
||||
|
|
||||
namespace UnityEngine.Rendering.PostProcessing |
|
||||
{ |
|
||||
[UnityEngine.Scripting.Preserve] |
|
||||
[Serializable] |
|
||||
public class SuperResolution |
|
||||
{ |
|
||||
public Func<PostProcessRenderContext, IFsr3UpscalerCallbacks> callbacksFactory { get; set; } = (context) => new Fsr3UpscalerCallbacksBase(); |
|
||||
|
|
||||
[Tooltip("Standard scaling ratio presets.")] |
|
||||
public Fsr3Upscaler.QualityMode qualityMode = Fsr3Upscaler.QualityMode.Quality; |
|
||||
|
|
||||
[Tooltip("Apply RCAS sharpening to the image after upscaling.")] |
|
||||
public bool performSharpenPass = true; |
|
||||
[Tooltip("Strength of the sharpening effect.")] |
|
||||
[Range(0, 1)] public float sharpness = 0.8f; |
|
||||
|
|
||||
[Tooltip("Choose where to get the exposure value from. Use auto-exposure from either FSR3 or Unity, provide a manual exposure texture, or use a default value.")] |
|
||||
public ExposureSource exposureSource = ExposureSource.Auto; |
|
||||
[Tooltip("Value by which the input signal will be divided, to get back to the original signal produced by the game.")] |
|
||||
public float preExposure = 1.0f; |
|
||||
[Tooltip("Optional 1x1 texture containing the exposure value for the current frame.")] |
|
||||
public Texture exposure = null; |
|
||||
|
|
||||
public enum ExposureSource |
|
||||
{ |
|
||||
Default, |
|
||||
Auto, |
|
||||
Unity, |
|
||||
Manual, |
|
||||
} |
|
||||
|
|
||||
[Tooltip("Enable a debug view to analyze the upscaling process.")] |
|
||||
public bool enableDebugView = false; |
|
||||
|
|
||||
[Tooltip("Optional texture to control the influence of the current frame on the reconstructed output. If unset, either an auto-generated or a default cleared reactive mask will be used.")] |
|
||||
public Texture reactiveMask = null; |
|
||||
[Tooltip("Optional texture for marking areas of specialist rendering which should be accounted for during the upscaling process. If unset, a default cleared mask will be used.")] |
|
||||
public Texture transparencyAndCompositionMask = null; |
|
||||
[Tooltip("Automatically generate a reactive mask based on the difference between opaque-only render output and the final render output including alpha transparencies.")] |
|
||||
public bool autoGenerateReactiveMask = true; |
|
||||
[Tooltip("Parameters to control the process of auto-generating a reactive mask.")] |
|
||||
public GenerateReactiveParameters generateReactiveParameters = new GenerateReactiveParameters(); |
|
||||
|
|
||||
[Serializable] |
|
||||
public class GenerateReactiveParameters |
|
||||
{ |
|
||||
[Tooltip("A value to scale the output")] |
|
||||
[Range(0, 2)] public float scale = 0.5f; |
|
||||
[Tooltip("A threshold value to generate a binary reactive mask")] |
|
||||
[Range(0, 1)] public float cutoffThreshold = 0.2f; |
|
||||
[Tooltip("A value to set for the binary reactive mask")] |
|
||||
[Range(0, 1)] public float binaryValue = 0.9f; |
|
||||
[Tooltip("Flags to determine how to generate the reactive mask")] |
|
||||
public Fsr3Upscaler.GenerateReactiveFlags flags = Fsr3Upscaler.GenerateReactiveFlags.ApplyTonemap | Fsr3Upscaler.GenerateReactiveFlags.ApplyThreshold | Fsr3Upscaler.GenerateReactiveFlags.UseComponentsMax; |
|
||||
} |
|
||||
|
|
||||
[Tooltip("(Experimental) Automatically generate and use Reactive mask and Transparency & composition mask internally.")] |
|
||||
public bool autoGenerateTransparencyAndComposition = false; |
|
||||
[Tooltip("Parameters to control the process of auto-generating transparency and composition masks.")] |
|
||||
public GenerateTcrParameters generateTransparencyAndCompositionParameters = new GenerateTcrParameters(); |
|
||||
|
|
||||
[Serializable] |
|
||||
public class GenerateTcrParameters |
|
||||
{ |
|
||||
[Tooltip("Setting this value too small will cause visual instability. Larger values can cause ghosting.")] |
|
||||
[Range(0, 1)] public float autoTcThreshold = 0.05f; |
|
||||
[Tooltip("Smaller values will increase stability at hard edges of translucent objects.")] |
|
||||
[Range(0, 2)] public float autoTcScale = 1.0f; |
|
||||
[Tooltip("Larger values result in more reactive pixels.")] |
|
||||
[Range(0, 10)] public float autoReactiveScale = 5.0f; |
|
||||
[Tooltip("Maximum value reactivity can reach.")] |
|
||||
[Range(0, 1)] public float autoReactiveMax = 0.9f; |
|
||||
} |
|
||||
|
|
||||
public Vector2 jitter { get; private set; } |
|
||||
public Vector2Int renderSize => _maxRenderSize; |
|
||||
public Vector2Int displaySize => _displaySize; |
|
||||
public RenderTargetIdentifier colorOpaqueOnly { get; set; } |
|
||||
|
|
||||
private Fsr3UpscalerContext _fsrContext; |
|
||||
private Vector2Int _maxRenderSize; |
|
||||
private Vector2Int _displaySize; |
|
||||
private bool _resetHistory; |
|
||||
|
|
||||
private IFsr3UpscalerCallbacks _callbacks; |
|
||||
|
|
||||
private readonly Fsr3Upscaler.DispatchDescription _dispatchDescription = new Fsr3Upscaler.DispatchDescription(); |
|
||||
private readonly Fsr3Upscaler.GenerateReactiveDescription _genReactiveDescription = new Fsr3Upscaler.GenerateReactiveDescription(); |
|
||||
|
|
||||
private Fsr3Upscaler.QualityMode _prevQualityMode; |
|
||||
private ExposureSource _prevExposureSource; |
|
||||
private Vector2Int _prevDisplaySize; |
|
||||
|
|
||||
private Rect _originalRect; |
|
||||
|
|
||||
public bool IsSupported() |
|
||||
{ |
|
||||
return SystemInfo.supportsComputeShaders && SystemInfo.supportsMotionVectors; |
|
||||
} |
|
||||
|
|
||||
public DepthTextureMode GetCameraFlags() |
|
||||
{ |
|
||||
return DepthTextureMode.Depth | DepthTextureMode.MotionVectors; |
|
||||
} |
|
||||
|
|
||||
public void Release() |
|
||||
{ |
|
||||
DestroyFsrContext(); |
|
||||
} |
|
||||
|
|
||||
public void ResetHistory() |
|
||||
{ |
|
||||
_resetHistory = true; |
|
||||
} |
|
||||
|
|
||||
public void ConfigureJitteredProjectionMatrix(PostProcessRenderContext context) |
|
||||
{ |
|
||||
ApplyJitter(context.camera); |
|
||||
} |
|
||||
|
|
||||
public void ConfigureCameraViewport(PostProcessRenderContext context) |
|
||||
{ |
|
||||
var camera = context.camera; |
|
||||
_originalRect = camera.rect; |
|
||||
|
|
||||
// Determine the desired rendering and display resolutions
|
|
||||
_displaySize = new Vector2Int(camera.pixelWidth, camera.pixelHeight); |
|
||||
Fsr3Upscaler.GetRenderResolutionFromQualityMode(out int maxRenderWidth, out int maxRenderHeight, _displaySize.x, _displaySize.y, qualityMode); |
|
||||
_maxRenderSize = new Vector2Int(maxRenderWidth, maxRenderHeight); |
|
||||
|
|
||||
// Render to a smaller portion of the screen by manipulating the camera's viewport rect
|
|
||||
camera.aspect = (float)_displaySize.x / _displaySize.y; |
|
||||
camera.rect = new Rect(0, 0, _originalRect.width * _maxRenderSize.x / _displaySize.x, _originalRect.height * _maxRenderSize.y / _displaySize.y); |
|
||||
} |
|
||||
|
|
||||
public void ResetCameraViewport(PostProcessRenderContext context) |
|
||||
{ |
|
||||
context.camera.rect = _originalRect; |
|
||||
} |
|
||||
|
|
||||
public void Render(PostProcessRenderContext context) |
|
||||
{ |
|
||||
var cmd = context.command; |
|
||||
cmd.BeginSample("FSR3 Upscaler"); |
|
||||
|
|
||||
// Monitor for any resolution changes and recreate the FSR3 Upscaler context if necessary
|
|
||||
// We can't create an FSR3 Upscaler context without info from the post-processing context, so delay the initial setup until here
|
|
||||
if (_fsrContext == null || _displaySize.x != _prevDisplaySize.x || _displaySize.y != _prevDisplaySize.y || qualityMode != _prevQualityMode || exposureSource != _prevExposureSource) |
|
||||
{ |
|
||||
DestroyFsrContext(); |
|
||||
CreateFsrContext(context); |
|
||||
} |
|
||||
|
|
||||
SetupDispatchDescription(context); |
|
||||
|
|
||||
if (autoGenerateReactiveMask) |
|
||||
{ |
|
||||
SetupAutoReactiveDescription(context); |
|
||||
|
|
||||
var scaledRenderSize = _genReactiveDescription.RenderSize; |
|
||||
cmd.GetTemporaryRT(Fsr3ShaderIDs.UavAutoReactive, scaledRenderSize.x, scaledRenderSize.y, 0, default, GraphicsFormat.R8_UNorm, 1, true); |
|
||||
_fsrContext.GenerateReactiveMask(_genReactiveDescription, cmd); |
|
||||
_dispatchDescription.Reactive = new ResourceView(Fsr3ShaderIDs.UavAutoReactive); |
|
||||
} |
|
||||
|
|
||||
_fsrContext.Dispatch(_dispatchDescription, cmd); |
|
||||
|
|
||||
cmd.EndSample("FSR3 Upscaler"); |
|
||||
|
|
||||
_resetHistory = false; |
|
||||
} |
|
||||
|
|
||||
private void CreateFsrContext(PostProcessRenderContext context) |
|
||||
{ |
|
||||
_prevQualityMode = qualityMode; |
|
||||
_prevExposureSource = exposureSource; |
|
||||
_prevDisplaySize = _displaySize; |
|
||||
|
|
||||
// Initialize FSR3 Upscaler context
|
|
||||
Fsr3Upscaler.InitializationFlags flags = 0; |
|
||||
if (context.camera.allowHDR) flags |= Fsr3Upscaler.InitializationFlags.EnableHighDynamicRange; |
|
||||
if (exposureSource == ExposureSource.Auto) flags |= Fsr3Upscaler.InitializationFlags.EnableAutoExposure; |
|
||||
if (RuntimeUtilities.IsDynamicResolutionEnabled(context.camera)) flags |= Fsr3Upscaler.InitializationFlags.EnableDynamicResolution; |
|
||||
|
|
||||
_callbacks = callbacksFactory(context); |
|
||||
_fsrContext = Fsr3Upscaler.CreateContext(_displaySize, _maxRenderSize, context.resources.computeShaders.superResolution, flags); |
|
||||
|
|
||||
// Apply a mipmap bias so that textures retain their sharpness
|
|
||||
float biasOffset = Fsr3Upscaler.GetMipmapBiasOffset(_maxRenderSize.x, _displaySize.x); |
|
||||
if (!float.IsNaN(biasOffset) && !float.IsInfinity(biasOffset)) |
|
||||
{ |
|
||||
_callbacks.ApplyMipmapBias(biasOffset); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private void DestroyFsrContext() |
|
||||
{ |
|
||||
if (_fsrContext != null) |
|
||||
{ |
|
||||
_fsrContext.Destroy(); |
|
||||
_fsrContext = null; |
|
||||
} |
|
||||
|
|
||||
if (_callbacks != null) |
|
||||
{ |
|
||||
// Undo the current mipmap bias offset
|
|
||||
_callbacks.UndoMipmapBias(); |
|
||||
_callbacks = null; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private void ApplyJitter(Camera camera) |
|
||||
{ |
|
||||
var scaledRenderSize = GetScaledRenderSize(camera); |
|
||||
|
|
||||
// Perform custom jittering of the camera's projection matrix according to FSR3's recipe
|
|
||||
int jitterPhaseCount = Fsr3Upscaler.GetJitterPhaseCount(scaledRenderSize.x, _displaySize.x); |
|
||||
Fsr3Upscaler.GetJitterOffset(out float jitterX, out float jitterY, Time.frameCount, jitterPhaseCount); |
|
||||
|
|
||||
_dispatchDescription.JitterOffset = new Vector2(jitterX, jitterY); |
|
||||
|
|
||||
jitterX = 2.0f * jitterX / scaledRenderSize.x; |
|
||||
jitterY = 2.0f * jitterY / scaledRenderSize.y; |
|
||||
|
|
||||
var jitterTranslationMatrix = Matrix4x4.Translate(new Vector3(jitterX, jitterY, 0)); |
|
||||
camera.nonJitteredProjectionMatrix = camera.projectionMatrix; |
|
||||
camera.projectionMatrix = jitterTranslationMatrix * camera.nonJitteredProjectionMatrix; |
|
||||
camera.useJitteredProjectionMatrixForTransparentRendering = true; |
|
||||
|
|
||||
jitter = new Vector2(jitterX, jitterY); |
|
||||
} |
|
||||
|
|
||||
private void SetupDispatchDescription(PostProcessRenderContext context) |
|
||||
{ |
|
||||
var camera = context.camera; |
|
||||
|
|
||||
// Set up the main FSR3 Upscaler dispatch parameters
|
|
||||
_dispatchDescription.Color = new ResourceView(context.source); |
|
||||
_dispatchDescription.Depth = new ResourceView(GetDepthTexture(context.camera), RenderTextureSubElement.Depth); |
|
||||
_dispatchDescription.MotionVectors = new ResourceView(BuiltinRenderTextureType.MotionVectors); |
|
||||
_dispatchDescription.Exposure = ResourceView.Unassigned; |
|
||||
_dispatchDescription.Reactive = ResourceView.Unassigned; |
|
||||
_dispatchDescription.TransparencyAndComposition = ResourceView.Unassigned; |
|
||||
|
|
||||
if (exposureSource == ExposureSource.Manual && exposure != null) _dispatchDescription.Exposure = new ResourceView(exposure); |
|
||||
if (exposureSource == ExposureSource.Unity) _dispatchDescription.Exposure = new ResourceView(context.autoExposureTexture); |
|
||||
if (reactiveMask != null) _dispatchDescription.Reactive = new ResourceView(reactiveMask); |
|
||||
if (transparencyAndCompositionMask != null) _dispatchDescription.TransparencyAndComposition = new ResourceView(transparencyAndCompositionMask); |
|
||||
|
|
||||
var scaledRenderSize = GetScaledRenderSize(context.camera); |
|
||||
|
|
||||
_dispatchDescription.Output = new ResourceView(context.destination); |
|
||||
_dispatchDescription.PreExposure = preExposure; |
|
||||
_dispatchDescription.EnableSharpening = performSharpenPass; |
|
||||
_dispatchDescription.Sharpness = sharpness; |
|
||||
_dispatchDescription.MotionVectorScale.x = -scaledRenderSize.x; |
|
||||
_dispatchDescription.MotionVectorScale.y = -scaledRenderSize.y; |
|
||||
_dispatchDescription.RenderSize = scaledRenderSize; |
|
||||
_dispatchDescription.UpscaleSize = _displaySize; |
|
||||
_dispatchDescription.FrameTimeDelta = Time.unscaledDeltaTime; |
|
||||
_dispatchDescription.CameraNear = camera.nearClipPlane; |
|
||||
_dispatchDescription.CameraFar = camera.farClipPlane; |
|
||||
_dispatchDescription.CameraFovAngleVertical = camera.fieldOfView * Mathf.Deg2Rad; |
|
||||
_dispatchDescription.ViewSpaceToMetersFactor = 1.0f; // 1 unit is 1 meter in Unity
|
|
||||
_dispatchDescription.Reset = _resetHistory; |
|
||||
_dispatchDescription.Flags = enableDebugView ? Fsr3Upscaler.DispatchFlags.DrawDebugView : 0; |
|
||||
|
|
||||
// Set up the parameters for the optional experimental auto-TCR feature
|
|
||||
_dispatchDescription.EnableAutoReactive = autoGenerateTransparencyAndComposition; |
|
||||
if (autoGenerateTransparencyAndComposition) |
|
||||
{ |
|
||||
_dispatchDescription.ColorOpaqueOnly = new ResourceView(colorOpaqueOnly); |
|
||||
_dispatchDescription.AutoTcThreshold = generateTransparencyAndCompositionParameters.autoTcThreshold; |
|
||||
_dispatchDescription.AutoTcScale = generateTransparencyAndCompositionParameters.autoTcScale; |
|
||||
_dispatchDescription.AutoReactiveScale = generateTransparencyAndCompositionParameters.autoReactiveScale; |
|
||||
_dispatchDescription.AutoReactiveMax = generateTransparencyAndCompositionParameters.autoReactiveMax; |
|
||||
} |
|
||||
|
|
||||
if (SystemInfo.usesReversedZBuffer) |
|
||||
{ |
|
||||
// Swap the near and far clip plane distances as FSR3 expects this when using inverted depth
|
|
||||
(_dispatchDescription.CameraNear, _dispatchDescription.CameraFar) = (_dispatchDescription.CameraFar, _dispatchDescription.CameraNear); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private void SetupAutoReactiveDescription(PostProcessRenderContext context) |
|
||||
{ |
|
||||
// Set up the parameters to auto-generate a reactive mask
|
|
||||
_genReactiveDescription.ColorOpaqueOnly = new ResourceView(colorOpaqueOnly); |
|
||||
_genReactiveDescription.ColorPreUpscale = new ResourceView(context.source); |
|
||||
_genReactiveDescription.OutReactive = new ResourceView(Fsr3ShaderIDs.UavAutoReactive); |
|
||||
_genReactiveDescription.RenderSize = GetScaledRenderSize(context.camera); |
|
||||
_genReactiveDescription.Scale = generateReactiveParameters.scale; |
|
||||
_genReactiveDescription.CutoffThreshold = generateReactiveParameters.cutoffThreshold; |
|
||||
_genReactiveDescription.BinaryValue = generateReactiveParameters.binaryValue; |
|
||||
_genReactiveDescription.Flags = generateReactiveParameters.flags; |
|
||||
} |
|
||||
|
|
||||
internal Vector2Int GetScaledRenderSize(Camera camera) |
|
||||
{ |
|
||||
if (!RuntimeUtilities.IsDynamicResolutionEnabled(camera)) |
|
||||
return _maxRenderSize; |
|
||||
|
|
||||
return new Vector2Int(Mathf.CeilToInt(_maxRenderSize.x * ScalableBufferManager.widthScaleFactor), Mathf.CeilToInt(_maxRenderSize.y * ScalableBufferManager.heightScaleFactor)); |
|
||||
} |
|
||||
|
|
||||
private static BuiltinRenderTextureType GetDepthTexture(Camera cam) |
|
||||
{ |
|
||||
RenderingPath renderingPath = cam.renderingPath; |
|
||||
return renderingPath == RenderingPath.Forward || renderingPath == RenderingPath.VertexLit ? BuiltinRenderTextureType.Depth : BuiltinRenderTextureType.CameraTarget; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,312 @@ |
|||||
|
using System; |
||||
|
using System.Runtime.InteropServices; |
||||
|
using FidelityFX.FSR2; |
||||
|
using UnityEngine.Experimental.Rendering; |
||||
|
|
||||
|
namespace UnityEngine.Rendering.PostProcessing |
||||
|
{ |
||||
|
[Scripting.Preserve] |
||||
|
[Serializable] |
||||
|
public class Upscaling |
||||
|
{ |
||||
|
public Func<PostProcessRenderContext, IUpscalerCallbacks> callbacksFactory { get; set; } = (context) => new UpscalerCallbacksBase(); |
||||
|
|
||||
|
public enum UpscalerType |
||||
|
{ |
||||
|
[InspectorName("FidelityFX Super Resolution 2.3 (FSR2)")] FSR2, |
||||
|
[InspectorName("FidelityFX Super Resolution 3.1 (FSR3)")] FSR3, |
||||
|
} |
||||
|
|
||||
|
[Tooltip("Which upscaling technology to use.")] |
||||
|
public UpscalerType upscalerType = UpscalerType.FSR2; |
||||
|
|
||||
|
[Tooltip("Standard scaling ratio presets.")] |
||||
|
public Fsr2.QualityMode qualityMode = Fsr2.QualityMode.Quality; |
||||
|
|
||||
|
[Tooltip("Apply sharpening to the image after upscaling.")] |
||||
|
public bool performSharpenPass = true; |
||||
|
[Tooltip("Strength of the sharpening effect.")] |
||||
|
[Range(0, 1)] public float sharpness = 0.8f; |
||||
|
|
||||
|
[Tooltip("Adjust the influence of motion vectors on temporal accumulation.")] |
||||
|
[Range(0, 1)] public float velocityFactor = 1.0f; |
||||
|
|
||||
|
[Tooltip("Choose where to get the exposure value from. Use auto-exposure from either the upscaler or Unity, provide a manual exposure texture, or use a default value.")] |
||||
|
public ExposureSource exposureSource = ExposureSource.Auto; |
||||
|
[Tooltip("Value by which the input signal will be divided, to get back to the original signal produced by the game.")] |
||||
|
public float preExposure = 1.0f; |
||||
|
[Tooltip("Optional 1x1 texture containing the exposure value for the current frame.")] |
||||
|
public Texture exposure = null; |
||||
|
|
||||
|
public enum ExposureSource |
||||
|
{ |
||||
|
Default, |
||||
|
Auto, |
||||
|
Unity, |
||||
|
Manual, |
||||
|
} |
||||
|
|
||||
|
[Tooltip("Enable a debug view to analyze the upscaling process.")] |
||||
|
public bool enableDebugView = false; |
||||
|
|
||||
|
[Tooltip("Optional texture to control the influence of the current frame on the reconstructed output. If unset, either an auto-generated or a default cleared reactive mask will be used.")] |
||||
|
public Texture reactiveMask = null; |
||||
|
[Tooltip("Optional texture for marking areas of specialist rendering which should be accounted for during the upscaling process. If unset, a default cleared mask will be used.")] |
||||
|
public Texture transparencyAndCompositionMask = null; |
||||
|
[Tooltip("Automatically generate a reactive mask based on the difference between opaque-only render output and the final render output including alpha transparencies.")] |
||||
|
public bool autoGenerateReactiveMask = true; |
||||
|
[Tooltip("Parameters to control the process of auto-generating a reactive mask.")] |
||||
|
public GenerateReactiveParameters generateReactiveParameters = new GenerateReactiveParameters(); |
||||
|
|
||||
|
[Serializable] |
||||
|
public class GenerateReactiveParameters |
||||
|
{ |
||||
|
[Tooltip("A value to scale the output")] |
||||
|
[Range(0, 2)] public float scale = 0.5f; |
||||
|
[Tooltip("A threshold value to generate a binary reactive mask")] |
||||
|
[Range(0, 1)] public float cutoffThreshold = 0.2f; |
||||
|
[Tooltip("A value to set for the binary reactive mask")] |
||||
|
[Range(0, 1)] public float binaryValue = 0.9f; |
||||
|
[Tooltip("Flags to determine how to generate the reactive mask")] |
||||
|
public Fsr2.GenerateReactiveFlags flags = Fsr2.GenerateReactiveFlags.ApplyTonemap | Fsr2.GenerateReactiveFlags.ApplyThreshold | Fsr2.GenerateReactiveFlags.UseComponentsMax; |
||||
|
} |
||||
|
|
||||
|
[Tooltip("(Experimental) Automatically generate and use Reactive mask and Transparency & composition mask internally.")] |
||||
|
public bool autoGenerateTransparencyAndComposition = false; |
||||
|
[Tooltip("Parameters to control the process of auto-generating transparency and composition masks.")] |
||||
|
public GenerateTcrParameters generateTransparencyAndCompositionParameters = new GenerateTcrParameters(); |
||||
|
|
||||
|
[Serializable] |
||||
|
public class GenerateTcrParameters |
||||
|
{ |
||||
|
[Tooltip("Setting this value too small will cause visual instability. Larger values can cause ghosting.")] |
||||
|
[Range(0, 1)] public float autoTcThreshold = 0.05f; |
||||
|
[Tooltip("Smaller values will increase stability at hard edges of translucent objects.")] |
||||
|
[Range(0, 2)] public float autoTcScale = 1.0f; |
||||
|
[Tooltip("Larger values result in more reactive pixels.")] |
||||
|
[Range(0, 10)] public float autoReactiveScale = 5.0f; |
||||
|
[Tooltip("Maximum value reactivity can reach.")] |
||||
|
[Range(0, 1)] public float autoReactiveMax = 0.9f; |
||||
|
} |
||||
|
|
||||
|
public Vector2 Jitter { get; private set; } |
||||
|
public Vector2 JitterOffset { get; private set; } |
||||
|
public Vector2Int MaxRenderSize => _maxRenderSize; |
||||
|
public Vector2Int UpscaleSize => _upscaleSize; |
||||
|
public bool Reset => _resetHistory; |
||||
|
public RenderTargetIdentifier ColorOpaqueOnly { get; set; } |
||||
|
|
||||
|
private bool _initialized; |
||||
|
private Upscaler _upscaler; |
||||
|
private Vector2Int _maxRenderSize; |
||||
|
private Vector2Int _upscaleSize; |
||||
|
private bool _resetHistory; |
||||
|
|
||||
|
private IUpscalerCallbacks _callbacks; |
||||
|
|
||||
|
private UpscalerType _prevUpscalerType; |
||||
|
private Fsr2.QualityMode _prevQualityMode; |
||||
|
private ExposureSource _prevExposureSource; |
||||
|
private Vector2Int _prevUpscaleSize; |
||||
|
|
||||
|
private Rect _originalRect; |
||||
|
|
||||
|
public bool IsSupported() |
||||
|
{ |
||||
|
return SystemInfo.supportsComputeShaders && SystemInfo.supportsMotionVectors; |
||||
|
} |
||||
|
|
||||
|
public DepthTextureMode GetCameraFlags() |
||||
|
{ |
||||
|
return DepthTextureMode.Depth | DepthTextureMode.MotionVectors; |
||||
|
} |
||||
|
|
||||
|
public void Release() |
||||
|
{ |
||||
|
DestroyUpscaler(); |
||||
|
} |
||||
|
|
||||
|
public void ResetHistory() |
||||
|
{ |
||||
|
_resetHistory = true; |
||||
|
} |
||||
|
|
||||
|
public void ConfigureJitteredProjectionMatrix(PostProcessRenderContext context) |
||||
|
{ |
||||
|
ApplyJitter(context.camera); |
||||
|
} |
||||
|
|
||||
|
public void ConfigureCameraViewport(PostProcessRenderContext context) |
||||
|
{ |
||||
|
var camera = context.camera; |
||||
|
_originalRect = camera.rect; |
||||
|
|
||||
|
// Determine the desired rendering and display resolutions
|
||||
|
_upscaleSize = new Vector2Int(camera.pixelWidth, camera.pixelHeight); |
||||
|
Fsr2.GetRenderResolutionFromQualityMode(out int maxRenderWidth, out int maxRenderHeight, _upscaleSize.x, _upscaleSize.y, qualityMode); |
||||
|
_maxRenderSize = new Vector2Int(maxRenderWidth, maxRenderHeight); |
||||
|
|
||||
|
// Render to a smaller portion of the screen by manipulating the camera's viewport rect
|
||||
|
camera.aspect = (float)_upscaleSize.x / _upscaleSize.y; |
||||
|
camera.rect = new Rect(0, 0, _originalRect.width * _maxRenderSize.x / _upscaleSize.x, _originalRect.height * _maxRenderSize.y / _upscaleSize.y); |
||||
|
} |
||||
|
|
||||
|
public void ResetCameraViewport(PostProcessRenderContext context) |
||||
|
{ |
||||
|
context.camera.rect = _originalRect; |
||||
|
} |
||||
|
|
||||
|
public void Render(PostProcessRenderContext context) |
||||
|
{ |
||||
|
// Monitor for any resolution changes and recreate the upscaler context if necessary
|
||||
|
// We can't create an upscaler context without info from the post-processing context, so delay the initial setup until here
|
||||
|
if (!_initialized || _upscaler == null || _upscaleSize.x != _prevUpscaleSize.x || _upscaleSize.y != _prevUpscaleSize.y || |
||||
|
upscalerType != _prevUpscalerType || qualityMode != _prevQualityMode || exposureSource != _prevExposureSource) |
||||
|
{ |
||||
|
DestroyUpscaler(); |
||||
|
CreateUpscaler(context); |
||||
|
} |
||||
|
|
||||
|
_upscaler?.Render(context, this); |
||||
|
|
||||
|
_resetHistory = false; |
||||
|
} |
||||
|
|
||||
|
private void CreateUpscaler(PostProcessRenderContext context) |
||||
|
{ |
||||
|
if (_upscaler == null || upscalerType != _prevUpscalerType) |
||||
|
{ |
||||
|
_upscaler = upscalerType switch |
||||
|
{ |
||||
|
UpscalerType.FSR2 when FSR2Upscaler.IsSupported => new FSR2Upscaler(), |
||||
|
UpscalerType.FSR3 when FSR3Upscaler.IsSupported => new FSR3Upscaler(), |
||||
|
_ => new FSR2Upscaler(), // Fallback for when the selected upscaler is not supported on the current hardware
|
||||
|
}; |
||||
|
|
||||
|
_prevUpscalerType = upscalerType; |
||||
|
} |
||||
|
|
||||
|
_prevQualityMode = qualityMode; |
||||
|
_prevExposureSource = exposureSource; |
||||
|
_prevUpscaleSize = _upscaleSize; |
||||
|
|
||||
|
_callbacks = callbacksFactory(context); |
||||
|
|
||||
|
_upscaler.CreateContext(context, this); |
||||
|
|
||||
|
// Apply a mipmap bias so that textures retain their sharpness
|
||||
|
float biasOffset = Fsr2.GetMipmapBiasOffset(_maxRenderSize.x, _upscaleSize.x); |
||||
|
if (_callbacks != null && !float.IsNaN(biasOffset) && !float.IsInfinity(biasOffset)) |
||||
|
{ |
||||
|
_callbacks.ApplyMipmapBias(biasOffset); |
||||
|
} |
||||
|
|
||||
|
_initialized = true; |
||||
|
} |
||||
|
|
||||
|
private void DestroyUpscaler() |
||||
|
{ |
||||
|
_initialized = false; |
||||
|
|
||||
|
_upscaler?.DestroyContext(); |
||||
|
|
||||
|
if (_callbacks != null) |
||||
|
{ |
||||
|
// Undo the current mipmap bias offset
|
||||
|
_callbacks.UndoMipmapBias(); |
||||
|
_callbacks = null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void ApplyJitter(Camera camera) |
||||
|
{ |
||||
|
var scaledRenderSize = GetScaledRenderSize(camera); |
||||
|
|
||||
|
// Perform custom jittering of the camera's projection matrix according to FSR's recipe
|
||||
|
int jitterPhaseCount = Fsr2.GetJitterPhaseCount(scaledRenderSize.x, _upscaleSize.x); |
||||
|
Fsr2.GetJitterOffset(out float jitterX, out float jitterY, Time.frameCount, jitterPhaseCount); |
||||
|
|
||||
|
JitterOffset = new Vector2(jitterX, jitterY); |
||||
|
|
||||
|
jitterX = 2.0f * jitterX / scaledRenderSize.x; |
||||
|
jitterY = 2.0f * jitterY / scaledRenderSize.y; |
||||
|
|
||||
|
var jitterTranslationMatrix = Matrix4x4.Translate(new Vector3(jitterX, jitterY, 0)); |
||||
|
camera.nonJitteredProjectionMatrix = camera.projectionMatrix; |
||||
|
camera.projectionMatrix = jitterTranslationMatrix * camera.nonJitteredProjectionMatrix; |
||||
|
camera.useJitteredProjectionMatrixForTransparentRendering = true; |
||||
|
|
||||
|
Jitter = new Vector2(jitterX, jitterY); |
||||
|
} |
||||
|
|
||||
|
internal Vector2Int GetScaledRenderSize(Camera camera) |
||||
|
{ |
||||
|
if (!RuntimeUtilities.IsDynamicResolutionEnabled(camera)) |
||||
|
return _maxRenderSize; |
||||
|
|
||||
|
return new Vector2Int(Mathf.CeilToInt(_maxRenderSize.x * ScalableBufferManager.widthScaleFactor), Mathf.CeilToInt(_maxRenderSize.y * ScalableBufferManager.heightScaleFactor)); |
||||
|
} |
||||
|
|
||||
|
internal static BuiltinRenderTextureType GetDepthTexture(Camera cam) |
||||
|
{ |
||||
|
return cam.renderingPath is RenderingPath.Forward or RenderingPath.VertexLit ? BuiltinRenderTextureType.Depth : BuiltinRenderTextureType.CameraTarget; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// A collection of callbacks required by the upscaler.
|
||||
|
/// This allows some customization by the game dev on how to integrate upscaling into their own game setup.
|
||||
|
/// </summary>
|
||||
|
public interface IUpscalerCallbacks |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Apply a mipmap bias to in-game textures to prevent them from becoming blurry as the internal rendering resolution lowers.
|
||||
|
/// This will need to be customized on a per-game basis, as there is no clear universal way to determine what are "in-game" textures.
|
||||
|
/// The default implementation will simply apply a mipmap bias to all 2D textures, which will include things like UI textures and which might miss things like terrain texture arrays.
|
||||
|
///
|
||||
|
/// Depending on how your game organizes its assets, you will want to create a filter that more specifically selects the textures that need to have this mipmap bias applied.
|
||||
|
/// You may also want to store the bias offset value and apply it to any assets that are loaded in on demand.
|
||||
|
/// </summary>
|
||||
|
void ApplyMipmapBias(float biasOffset); |
||||
|
|
||||
|
void UndoMipmapBias(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Default implementation of IUpscalerCallbacks.
|
||||
|
/// These are fine for testing but a proper game will want to extend and override these methods.
|
||||
|
/// </summary>
|
||||
|
public class UpscalerCallbacksBase: IUpscalerCallbacks |
||||
|
{ |
||||
|
protected float CurrentBiasOffset = 0; |
||||
|
|
||||
|
public virtual void ApplyMipmapBias(float biasOffset) |
||||
|
{ |
||||
|
if (float.IsNaN(biasOffset) || float.IsInfinity(biasOffset)) |
||||
|
return; |
||||
|
|
||||
|
CurrentBiasOffset += biasOffset; |
||||
|
|
||||
|
if (Mathf.Approximately(CurrentBiasOffset, 0f)) |
||||
|
{ |
||||
|
CurrentBiasOffset = 0f; |
||||
|
} |
||||
|
|
||||
|
foreach (var texture in Resources.FindObjectsOfTypeAll<Texture2D>()) |
||||
|
{ |
||||
|
if (texture.mipmapCount <= 1) |
||||
|
continue; |
||||
|
|
||||
|
texture.mipMapBias += biasOffset; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public virtual void UndoMipmapBias() |
||||
|
{ |
||||
|
if (CurrentBiasOffset == 0f) |
||||
|
return; |
||||
|
|
||||
|
ApplyMipmapBias(-CurrentBiasOffset); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: bd735f2dacb54f5e9a0722ec5851acee |
||||
|
timeCreated: 1729512005 |
||||
@ -0,0 +1,3 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: a0c49999ca0d45bfb0922a4f7366ae28 |
||||
|
timeCreated: 1729511667 |
||||
@ -0,0 +1,124 @@ |
|||||
|
using FidelityFX; |
||||
|
using FidelityFX.FSR2; |
||||
|
using UnityEngine.Experimental.Rendering; |
||||
|
|
||||
|
namespace UnityEngine.Rendering.PostProcessing |
||||
|
{ |
||||
|
internal class FSR2Upscaler: Upscaler |
||||
|
{ |
||||
|
public static bool IsSupported => SystemInfo.supportsComputeShaders; |
||||
|
|
||||
|
private Fsr2Context _fsrContext; |
||||
|
|
||||
|
private readonly Fsr2.DispatchDescription _dispatchDescription = new(); |
||||
|
private readonly Fsr2.GenerateReactiveDescription _genReactiveDescription = new(); |
||||
|
|
||||
|
public override void CreateContext(PostProcessRenderContext context, Upscaling config) |
||||
|
{ |
||||
|
// Initialize FSR2 context
|
||||
|
Fsr2.InitializationFlags flags = 0; |
||||
|
if (context.camera.allowHDR) flags |= Fsr2.InitializationFlags.EnableHighDynamicRange; |
||||
|
if (config.exposureSource == Upscaling.ExposureSource.Auto) flags |= Fsr2.InitializationFlags.EnableAutoExposure; |
||||
|
if (RuntimeUtilities.IsDynamicResolutionEnabled(context.camera)) flags |= Fsr2.InitializationFlags.EnableDynamicResolution; |
||||
|
|
||||
|
_fsrContext = Fsr2.CreateContext(config.UpscaleSize, config.MaxRenderSize, context.resources.computeShaders.fsr2Upscaler, flags); |
||||
|
} |
||||
|
|
||||
|
public override void DestroyContext() |
||||
|
{ |
||||
|
if (_fsrContext != null) |
||||
|
{ |
||||
|
_fsrContext.Destroy(); |
||||
|
_fsrContext = null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override void Render(PostProcessRenderContext context, Upscaling config) |
||||
|
{ |
||||
|
var cmd = context.command; |
||||
|
cmd.BeginSample("FSR2"); |
||||
|
|
||||
|
SetupDispatchDescription(context, config); |
||||
|
|
||||
|
if (config.autoGenerateReactiveMask) |
||||
|
{ |
||||
|
SetupAutoReactiveDescription(context, config); |
||||
|
|
||||
|
var scaledRenderSize = _genReactiveDescription.RenderSize; |
||||
|
cmd.GetTemporaryRT(Fsr2ShaderIDs.UavAutoReactive, scaledRenderSize.x, scaledRenderSize.y, 0, default, GraphicsFormat.R8_UNorm, 1, true); |
||||
|
_fsrContext.GenerateReactiveMask(_genReactiveDescription, cmd); |
||||
|
_dispatchDescription.Reactive = new ResourceView(Fsr2ShaderIDs.UavAutoReactive); |
||||
|
} |
||||
|
|
||||
|
_fsrContext.Dispatch(_dispatchDescription, cmd); |
||||
|
|
||||
|
cmd.EndSample("FSR2"); |
||||
|
} |
||||
|
|
||||
|
private void SetupDispatchDescription(PostProcessRenderContext context, Upscaling config) |
||||
|
{ |
||||
|
var camera = context.camera; |
||||
|
|
||||
|
// Set up the main FSR2 dispatch parameters
|
||||
|
_dispatchDescription.Color = new ResourceView(context.source); |
||||
|
_dispatchDescription.Depth = new ResourceView(Upscaling.GetDepthTexture(context.camera), RenderTextureSubElement.Depth); |
||||
|
_dispatchDescription.MotionVectors = new ResourceView(BuiltinRenderTextureType.MotionVectors); |
||||
|
_dispatchDescription.Exposure = ResourceView.Unassigned; |
||||
|
_dispatchDescription.Reactive = ResourceView.Unassigned; |
||||
|
_dispatchDescription.TransparencyAndComposition = ResourceView.Unassigned; |
||||
|
|
||||
|
if (config.exposureSource == Upscaling.ExposureSource.Manual && config.exposure != null) _dispatchDescription.Exposure = new ResourceView(config.exposure); |
||||
|
if (config.exposureSource == Upscaling.ExposureSource.Unity) _dispatchDescription.Exposure = new ResourceView(context.autoExposureTexture); |
||||
|
if (config.reactiveMask != null) _dispatchDescription.Reactive = new ResourceView(config.reactiveMask); |
||||
|
if (config.transparencyAndCompositionMask != null) _dispatchDescription.TransparencyAndComposition = new ResourceView(config.transparencyAndCompositionMask); |
||||
|
|
||||
|
var scaledRenderSize = config.GetScaledRenderSize(context.camera); |
||||
|
|
||||
|
_dispatchDescription.Output = new ResourceView(context.destination); |
||||
|
_dispatchDescription.PreExposure = config.preExposure; |
||||
|
_dispatchDescription.EnableSharpening = config.performSharpenPass; |
||||
|
_dispatchDescription.Sharpness = config.sharpness; |
||||
|
_dispatchDescription.JitterOffset = config.JitterOffset; |
||||
|
_dispatchDescription.MotionVectorScale.x = -scaledRenderSize.x; |
||||
|
_dispatchDescription.MotionVectorScale.y = -scaledRenderSize.y; |
||||
|
_dispatchDescription.RenderSize = scaledRenderSize; |
||||
|
_dispatchDescription.InputResourceSize = scaledRenderSize; |
||||
|
_dispatchDescription.FrameTimeDelta = Time.unscaledDeltaTime; |
||||
|
_dispatchDescription.CameraNear = camera.nearClipPlane; |
||||
|
_dispatchDescription.CameraFar = camera.farClipPlane; |
||||
|
_dispatchDescription.CameraFovAngleVertical = camera.fieldOfView * Mathf.Deg2Rad; |
||||
|
_dispatchDescription.ViewSpaceToMetersFactor = 1.0f; // 1 unit is 1 meter in Unity
|
||||
|
_dispatchDescription.Reset = config.Reset; |
||||
|
|
||||
|
// Set up the parameters for the optional experimental auto-TCR feature
|
||||
|
_dispatchDescription.EnableAutoReactive = config.autoGenerateTransparencyAndComposition; |
||||
|
if (config.autoGenerateTransparencyAndComposition) |
||||
|
{ |
||||
|
_dispatchDescription.ColorOpaqueOnly = new ResourceView(config.ColorOpaqueOnly); |
||||
|
_dispatchDescription.AutoTcThreshold = config.generateTransparencyAndCompositionParameters.autoTcThreshold; |
||||
|
_dispatchDescription.AutoTcScale = config.generateTransparencyAndCompositionParameters.autoTcScale; |
||||
|
_dispatchDescription.AutoReactiveScale = config.generateTransparencyAndCompositionParameters.autoReactiveScale; |
||||
|
_dispatchDescription.AutoReactiveMax = config.generateTransparencyAndCompositionParameters.autoReactiveMax; |
||||
|
} |
||||
|
|
||||
|
if (SystemInfo.usesReversedZBuffer) |
||||
|
{ |
||||
|
// Swap the near and far clip plane distances as FSR2 expects this when using inverted depth
|
||||
|
(_dispatchDescription.CameraNear, _dispatchDescription.CameraFar) = (_dispatchDescription.CameraFar, _dispatchDescription.CameraNear); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void SetupAutoReactiveDescription(PostProcessRenderContext context, Upscaling config) |
||||
|
{ |
||||
|
// Set up the parameters to auto-generate a reactive mask
|
||||
|
_genReactiveDescription.ColorOpaqueOnly = new ResourceView(config.ColorOpaqueOnly); |
||||
|
_genReactiveDescription.ColorPreUpscale = new ResourceView(context.source); |
||||
|
_genReactiveDescription.OutReactive = new ResourceView(Fsr2ShaderIDs.UavAutoReactive); |
||||
|
_genReactiveDescription.RenderSize = config.GetScaledRenderSize(context.camera); |
||||
|
_genReactiveDescription.Scale = config.generateReactiveParameters.scale; |
||||
|
_genReactiveDescription.CutoffThreshold = config.generateReactiveParameters.cutoffThreshold; |
||||
|
_genReactiveDescription.BinaryValue = config.generateReactiveParameters.binaryValue; |
||||
|
_genReactiveDescription.Flags = config.generateReactiveParameters.flags; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,5 +1,5 @@ |
|||||
fileFormatVersion: 2 |
fileFormatVersion: 2 |
||||
guid: 804fb4cfea0948247a52576cc4a79609 |
|
||||
|
guid: a0118021cf3d4485b761155cbdcaa35d |
||||
MonoImporter: |
MonoImporter: |
||||
externalObjects: {} |
externalObjects: {} |
||||
serializedVersion: 2 |
serializedVersion: 2 |
||||
@ -0,0 +1,125 @@ |
|||||
|
using FidelityFX; |
||||
|
using FidelityFX.FSR3; |
||||
|
using UnityEngine.Experimental.Rendering; |
||||
|
|
||||
|
namespace UnityEngine.Rendering.PostProcessing |
||||
|
{ |
||||
|
internal class FSR3Upscaler: Upscaler |
||||
|
{ |
||||
|
public static bool IsSupported => SystemInfo.supportsComputeShaders; |
||||
|
|
||||
|
private Fsr3UpscalerContext _fsrContext; |
||||
|
|
||||
|
private readonly Fsr3Upscaler.DispatchDescription _dispatchDescription = new(); |
||||
|
private readonly Fsr3Upscaler.GenerateReactiveDescription _genReactiveDescription = new(); |
||||
|
|
||||
|
public override void CreateContext(PostProcessRenderContext context, Upscaling config) |
||||
|
{ |
||||
|
// Initialize FSR3 Upscaler context
|
||||
|
Fsr3Upscaler.InitializationFlags flags = 0; |
||||
|
if (context.camera.allowHDR) flags |= Fsr3Upscaler.InitializationFlags.EnableHighDynamicRange; |
||||
|
if (config.exposureSource == Upscaling.ExposureSource.Auto) flags |= Fsr3Upscaler.InitializationFlags.EnableAutoExposure; |
||||
|
if (RuntimeUtilities.IsDynamicResolutionEnabled(context.camera)) flags |= Fsr3Upscaler.InitializationFlags.EnableDynamicResolution; |
||||
|
|
||||
|
_fsrContext = Fsr3Upscaler.CreateContext(config.UpscaleSize, config.MaxRenderSize, context.resources.computeShaders.fsr3Upscaler, flags); |
||||
|
} |
||||
|
|
||||
|
public override void DestroyContext() |
||||
|
{ |
||||
|
if (_fsrContext != null) |
||||
|
{ |
||||
|
_fsrContext.Destroy(); |
||||
|
_fsrContext = null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override void Render(PostProcessRenderContext context, Upscaling config) |
||||
|
{ |
||||
|
var cmd = context.command; |
||||
|
cmd.BeginSample("FSR3 Upscaler"); |
||||
|
|
||||
|
SetupDispatchDescription(context, config); |
||||
|
|
||||
|
if (config.autoGenerateReactiveMask) |
||||
|
{ |
||||
|
SetupAutoReactiveDescription(context, config); |
||||
|
|
||||
|
var scaledRenderSize = _genReactiveDescription.RenderSize; |
||||
|
cmd.GetTemporaryRT(Fsr3ShaderIDs.UavAutoReactive, scaledRenderSize.x, scaledRenderSize.y, 0, default, GraphicsFormat.R8_UNorm, 1, true); |
||||
|
_fsrContext.GenerateReactiveMask(_genReactiveDescription, cmd); |
||||
|
_dispatchDescription.Reactive = new ResourceView(Fsr3ShaderIDs.UavAutoReactive); |
||||
|
} |
||||
|
|
||||
|
_fsrContext.Dispatch(_dispatchDescription, cmd); |
||||
|
|
||||
|
cmd.EndSample("FSR3 Upscaler"); |
||||
|
} |
||||
|
|
||||
|
private void SetupDispatchDescription(PostProcessRenderContext context, Upscaling config) |
||||
|
{ |
||||
|
var camera = context.camera; |
||||
|
|
||||
|
// Set up the main FSR3 Upscaler dispatch parameters
|
||||
|
_dispatchDescription.Color = new ResourceView(context.source); |
||||
|
_dispatchDescription.Depth = new ResourceView(Upscaling.GetDepthTexture(context.camera), RenderTextureSubElement.Depth); |
||||
|
_dispatchDescription.MotionVectors = new ResourceView(BuiltinRenderTextureType.MotionVectors); |
||||
|
_dispatchDescription.Exposure = ResourceView.Unassigned; |
||||
|
_dispatchDescription.Reactive = ResourceView.Unassigned; |
||||
|
_dispatchDescription.TransparencyAndComposition = ResourceView.Unassigned; |
||||
|
|
||||
|
if (config.exposureSource == Upscaling.ExposureSource.Manual && config.exposure != null) _dispatchDescription.Exposure = new ResourceView(config.exposure); |
||||
|
if (config.exposureSource == Upscaling.ExposureSource.Unity) _dispatchDescription.Exposure = new ResourceView(context.autoExposureTexture); |
||||
|
if (config.reactiveMask != null) _dispatchDescription.Reactive = new ResourceView(config.reactiveMask); |
||||
|
if (config.transparencyAndCompositionMask != null) _dispatchDescription.TransparencyAndComposition = new ResourceView(config.transparencyAndCompositionMask); |
||||
|
|
||||
|
var scaledRenderSize = config.GetScaledRenderSize(context.camera); |
||||
|
|
||||
|
_dispatchDescription.Output = new ResourceView(context.destination); |
||||
|
_dispatchDescription.PreExposure = config.preExposure; |
||||
|
_dispatchDescription.EnableSharpening = config.performSharpenPass; |
||||
|
_dispatchDescription.Sharpness = config.sharpness; |
||||
|
_dispatchDescription.JitterOffset = config.JitterOffset; |
||||
|
_dispatchDescription.MotionVectorScale.x = -scaledRenderSize.x; |
||||
|
_dispatchDescription.MotionVectorScale.y = -scaledRenderSize.y; |
||||
|
_dispatchDescription.RenderSize = scaledRenderSize; |
||||
|
_dispatchDescription.UpscaleSize = config.UpscaleSize; |
||||
|
_dispatchDescription.FrameTimeDelta = Time.unscaledDeltaTime; |
||||
|
_dispatchDescription.CameraNear = camera.nearClipPlane; |
||||
|
_dispatchDescription.CameraFar = camera.farClipPlane; |
||||
|
_dispatchDescription.CameraFovAngleVertical = camera.fieldOfView * Mathf.Deg2Rad; |
||||
|
_dispatchDescription.ViewSpaceToMetersFactor = 1.0f; // 1 unit is 1 meter in Unity
|
||||
|
_dispatchDescription.VelocityFactor = config.velocityFactor; |
||||
|
_dispatchDescription.Reset = config.Reset; |
||||
|
|
||||
|
// Set up the parameters for the optional experimental auto-TCR feature
|
||||
|
_dispatchDescription.EnableAutoReactive = config.autoGenerateTransparencyAndComposition; |
||||
|
if (config.autoGenerateTransparencyAndComposition) |
||||
|
{ |
||||
|
_dispatchDescription.ColorOpaqueOnly = new ResourceView(config.ColorOpaqueOnly); |
||||
|
_dispatchDescription.AutoTcThreshold = config.generateTransparencyAndCompositionParameters.autoTcThreshold; |
||||
|
_dispatchDescription.AutoTcScale = config.generateTransparencyAndCompositionParameters.autoTcScale; |
||||
|
_dispatchDescription.AutoReactiveScale = config.generateTransparencyAndCompositionParameters.autoReactiveScale; |
||||
|
_dispatchDescription.AutoReactiveMax = config.generateTransparencyAndCompositionParameters.autoReactiveMax; |
||||
|
} |
||||
|
|
||||
|
if (SystemInfo.usesReversedZBuffer) |
||||
|
{ |
||||
|
// Swap the near and far clip plane distances as FSR3 Upscaler expects this when using inverted depth
|
||||
|
(_dispatchDescription.CameraNear, _dispatchDescription.CameraFar) = (_dispatchDescription.CameraFar, _dispatchDescription.CameraNear); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void SetupAutoReactiveDescription(PostProcessRenderContext context, Upscaling config) |
||||
|
{ |
||||
|
// Set up the parameters to auto-generate a reactive mask
|
||||
|
_genReactiveDescription.ColorOpaqueOnly = new ResourceView(config.ColorOpaqueOnly); |
||||
|
_genReactiveDescription.ColorPreUpscale = new ResourceView(context.source); |
||||
|
_genReactiveDescription.OutReactive = new ResourceView(Fsr3ShaderIDs.UavAutoReactive); |
||||
|
_genReactiveDescription.RenderSize = config.GetScaledRenderSize(context.camera); |
||||
|
_genReactiveDescription.Scale = config.generateReactiveParameters.scale; |
||||
|
_genReactiveDescription.CutoffThreshold = config.generateReactiveParameters.cutoffThreshold; |
||||
|
_genReactiveDescription.BinaryValue = config.generateReactiveParameters.binaryValue; |
||||
|
_genReactiveDescription.Flags = (Fsr3Upscaler.GenerateReactiveFlags)config.generateReactiveParameters.flags; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: fbdc9b27493f9ee43aa512e20a9ce7bf |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,13 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace UnityEngine.Rendering.PostProcessing |
||||
|
{ |
||||
|
internal abstract class Upscaler |
||||
|
{ |
||||
|
public abstract void CreateContext(PostProcessRenderContext context, Upscaling config); |
||||
|
|
||||
|
public abstract void DestroyContext(); |
||||
|
|
||||
|
public abstract void Render(PostProcessRenderContext context, Upscaling config); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: fd3ec2f422404d659f599fbfaf38dcd7 |
||||
|
timeCreated: 1729512050 |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue