You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
179 lines
8.6 KiB
179 lines
8.6 KiB
using System;
|
|
using System.Runtime.InteropServices;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
|
|
namespace FidelityFX
|
|
{
|
|
internal abstract class Fsr2Pipeline: IDisposable
|
|
{
|
|
private readonly Fsr2Callbacks _callbacks;
|
|
protected readonly ComputeBuffer Constants;
|
|
|
|
protected ComputeShader ComputeShader;
|
|
protected int KernelIndex;
|
|
|
|
// Shader resource views, i.e. read-only bindings
|
|
protected static readonly int SrvInputColor = Shader.PropertyToID("r_input_color_jittered");
|
|
protected static readonly int SrvOpaqueOnly = Shader.PropertyToID("r_input_opaque_only");
|
|
protected static readonly int SrvInputMotionVectors = Shader.PropertyToID("r_input_motion_vectors");
|
|
protected static readonly int SrvInputDepth = Shader.PropertyToID("r_input_depth");
|
|
protected static readonly int SrvInputExposure = Shader.PropertyToID("r_input_exposure");
|
|
protected static readonly int SrvRcasInput = Shader.PropertyToID("r_rcas_input");
|
|
|
|
// Unordered access views, i.e. random read/write bindings
|
|
protected static readonly int UavUpscaledOutput = Shader.PropertyToID("rw_upscaled_output");
|
|
protected static readonly int UavExposureMipLumaChange = Shader.PropertyToID("rw_img_mip_shading_change");
|
|
protected static readonly int UavExposureMip5 = Shader.PropertyToID("rw_img_mip_5");
|
|
protected static readonly int UavAutoExposure = Shader.PropertyToID("rw_auto_exposure");
|
|
protected static readonly int UavSpdAtomicCount = Shader.PropertyToID("rw_spd_global_atomic");
|
|
|
|
// Constant buffer bindings
|
|
protected static readonly int CbFsr2 = Shader.PropertyToID("cbFSR2");
|
|
protected static readonly int CbSpd = Shader.PropertyToID("cbSPD");
|
|
protected static readonly int CbRcas = Shader.PropertyToID("cbRCAS");
|
|
protected static readonly int CbGenReactive = Shader.PropertyToID("cbGenerateReactive");
|
|
|
|
protected Fsr2Pipeline(Fsr2Callbacks callbacks, ComputeBuffer constants)
|
|
{
|
|
_callbacks = callbacks;
|
|
Constants = constants;
|
|
}
|
|
|
|
public virtual void Dispose()
|
|
{
|
|
UnloadComputeShader();
|
|
}
|
|
|
|
public abstract void ScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int dispatchX, int dispatchY);
|
|
|
|
protected void LoadComputeShader(string name, Fsr2.InitializationFlags flags)
|
|
{
|
|
LoadComputeShader(name, flags, ref ComputeShader, out KernelIndex);
|
|
}
|
|
|
|
private void LoadComputeShader(string name, Fsr2.InitializationFlags flags, ref ComputeShader shaderRef, out int kernelIndex)
|
|
{
|
|
if (shaderRef == null)
|
|
shaderRef = _callbacks.LoadComputeShader(name);
|
|
|
|
kernelIndex = shaderRef.FindKernel("CS");
|
|
|
|
// This mirrors the permutation rules from the CreatePipeline* functions
|
|
if ((flags & Fsr2.InitializationFlags.EnableHighDynamicRange) != 0) shaderRef.EnableKeyword("FFX_FSR2_OPTION_HDR_COLOR_INPUT");
|
|
if ((flags & Fsr2.InitializationFlags.EnableDisplayResolutionMotionVectors) == 0) shaderRef.EnableKeyword("FFX_FSR2_OPTION_LOW_RESOLUTION_MOTION_VECTORS");
|
|
if ((flags & Fsr2.InitializationFlags.EnableMotionVectorsJitterCancellation) != 0) shaderRef.EnableKeyword("FFX_FSR2_OPTION_JITTERED_MOTION_VECTORS");
|
|
if ((flags & Fsr2.InitializationFlags.EnableDepthInverted) != 0) shaderRef.EnableKeyword("FFX_FSR2_OPTION_INVERTED_DEPTH");
|
|
// TODO: enable FFX_FSR2_OPTION_REPROJECT_USE_LANCZOS_TYPE if the device capabilities allow (default subgroup size == 32 or 64)
|
|
// TODO: enable FFX_HALF if FP16 is supported (except RCAS)
|
|
}
|
|
|
|
private void UnloadComputeShader()
|
|
{
|
|
UnloadComputeShader(ref ComputeShader);
|
|
}
|
|
|
|
private void UnloadComputeShader(ref ComputeShader shaderRef)
|
|
{
|
|
if (shaderRef == null)
|
|
return;
|
|
|
|
_callbacks.UnloadComputeShader(shaderRef);
|
|
shaderRef = null;
|
|
}
|
|
}
|
|
|
|
internal class Fsr2ComputeLuminancePyramidPipeline : Fsr2Pipeline
|
|
{
|
|
private readonly ComputeBuffer _spdConstants;
|
|
|
|
public Fsr2ComputeLuminancePyramidPipeline(Fsr2Callbacks callbacks, Fsr2.InitializationFlags flags, ComputeBuffer constants, ComputeBuffer spdConstants)
|
|
: base(callbacks, constants)
|
|
{
|
|
_spdConstants = spdConstants;
|
|
|
|
LoadComputeShader("FSR2/ffx_fsr2_compute_luminance_pyramid_pass", flags);
|
|
}
|
|
|
|
public override void ScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int dispatchX, int dispatchY)
|
|
{
|
|
commandBuffer.SetComputeConstantBufferParam(ComputeShader, CbFsr2, Constants, 0, Marshal.SizeOf<Fsr2.Fsr2Constants>());
|
|
commandBuffer.SetComputeConstantBufferParam(ComputeShader, CbSpd, _spdConstants, 0, Marshal.SizeOf<Fsr2.SpdConstants>());
|
|
|
|
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
|
|
}
|
|
}
|
|
|
|
internal class Fsr2AccumulatePipeline : Fsr2Pipeline
|
|
{
|
|
public Fsr2AccumulatePipeline(Fsr2Callbacks callbacks, Fsr2.InitializationFlags flags, ComputeBuffer constants)
|
|
: base(callbacks, constants)
|
|
{
|
|
LoadComputeShader("FSR2/ffx_fsr2_accumulate_pass", flags);
|
|
}
|
|
|
|
public override void ScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int dispatchX, int dispatchY)
|
|
{
|
|
//throw new NotImplementedException();
|
|
}
|
|
}
|
|
|
|
internal class Fsr2AccumulateSharpenPipeline : Fsr2AccumulatePipeline
|
|
{
|
|
private readonly ComputeShader _shaderCopy;
|
|
|
|
public Fsr2AccumulateSharpenPipeline(Fsr2Callbacks callbacks, Fsr2.InitializationFlags flags, ComputeBuffer constants)
|
|
: base(callbacks, flags, constants)
|
|
{
|
|
// Simply loading the accumulate_pass compute shader will give us the same instance as the non-sharpen pipeline
|
|
// So we have to clone the shader instance and set the extra keyword on the new copy
|
|
_shaderCopy = UnityEngine.Object.Instantiate(ComputeShader);
|
|
foreach (var keyword in ComputeShader.enabledKeywords)
|
|
{
|
|
_shaderCopy.EnableKeyword(keyword.name);
|
|
}
|
|
_shaderCopy.EnableKeyword("FFX_FSR2_OPTION_APPLY_SHARPENING");
|
|
}
|
|
|
|
public override void ScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int dispatchX, int dispatchY)
|
|
{
|
|
// Temporarily swap around the shaders so that the dispatch will bind and execute the correct one
|
|
ComputeShader tmp = ComputeShader;
|
|
ComputeShader = _shaderCopy;
|
|
base.ScheduleDispatch(commandBuffer, dispatchParams, dispatchX, dispatchY);
|
|
ComputeShader = tmp;
|
|
}
|
|
|
|
public override void Dispose()
|
|
{
|
|
// Since we instantiated this copy, we have to destroy it instead of unloading the shader resource
|
|
UnityEngine.Object.Destroy(_shaderCopy);
|
|
base.Dispose();
|
|
}
|
|
}
|
|
|
|
internal class Fsr2RcasPipeline : Fsr2Pipeline
|
|
{
|
|
private readonly ComputeBuffer _rcasConstants;
|
|
|
|
public Fsr2RcasPipeline(Fsr2Callbacks callbacks, Fsr2.InitializationFlags flags, ComputeBuffer constants, ComputeBuffer rcasConstants)
|
|
: base(callbacks, constants)
|
|
{
|
|
_rcasConstants = rcasConstants;
|
|
|
|
LoadComputeShader("FSR2/ffx_fsr2_rcas_pass", flags);
|
|
}
|
|
|
|
public override void ScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int dispatchX, int dispatchY)
|
|
{
|
|
// Run the RCAS sharpening filter on the upscaled image
|
|
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputExposure, dispatchParams.Exposure);
|
|
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvRcasInput, dispatchParams.Input);
|
|
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, UavUpscaledOutput, dispatchParams.Output);
|
|
commandBuffer.SetComputeConstantBufferParam(ComputeShader, CbFsr2, Constants, 0, Marshal.SizeOf<Fsr2.Fsr2Constants>());
|
|
commandBuffer.SetComputeConstantBufferParam(ComputeShader, CbRcas, _rcasConstants, 0, Marshal.SizeOf<Fsr2.RcasConstants>());
|
|
|
|
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
|
|
}
|
|
}
|
|
}
|