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.
224 lines
9.4 KiB
224 lines
9.4 KiB
#if UNITY_PS5
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Runtime.InteropServices;
|
|
using UnityEngine.Experimental.Rendering;
|
|
using WW1.PlayStation;
|
|
|
|
namespace UnityEngine.Rendering.HighDefinition.AMD.PSSR
|
|
{
|
|
public class PSSRUpscalerPlugin: UpscalerPlugin
|
|
{
|
|
public override string name => "PSSR";
|
|
public override bool isSupported => UnityEngine.PS5.Utility.isTrinityMode;
|
|
public override bool isMLBased => true;
|
|
|
|
private static readonly Queue<uint> ContextPool = new((int)PSSRPlugin.MaxNumContexts);
|
|
private static bool _pluginInitialized;
|
|
|
|
public override bool Load()
|
|
{
|
|
try
|
|
{
|
|
if (PSSRPlugin.Init() < 0)
|
|
{
|
|
Debug.LogError("Failed to initialize PSSR plugin!");
|
|
_pluginInitialized = false;
|
|
return false;
|
|
}
|
|
}
|
|
catch (DllNotFoundException)
|
|
{
|
|
Debug.LogError("PSSR plugin not found!");
|
|
_pluginInitialized = false;
|
|
return false;
|
|
}
|
|
|
|
for (uint index = 0; index < PSSRPlugin.MaxNumContexts; ++index)
|
|
{
|
|
ContextPool.Enqueue(index);
|
|
}
|
|
|
|
_pluginInitialized = true;
|
|
return true;
|
|
}
|
|
|
|
public override bool IsLoaded()
|
|
{
|
|
return _pluginInitialized;
|
|
}
|
|
|
|
public override UpscalerContext CreateContext(in FSR2CommandInitializationData initSettings)
|
|
{
|
|
if (!_pluginInitialized)
|
|
{
|
|
Debug.LogWarning("PSSR plugin is not initialized!");
|
|
return null;
|
|
}
|
|
|
|
if (!ContextPool.TryDequeue(out uint contextIndex))
|
|
{
|
|
Debug.LogError("Ran out of PSSR contexts to allocate!");
|
|
return null;
|
|
}
|
|
|
|
PSSRUpscalerContext context = new();
|
|
context.Init(initSettings, contextIndex);
|
|
return context;
|
|
}
|
|
|
|
public override async void DestroyContext(UpscalerContext context)
|
|
{
|
|
var pssrContext = (PSSRUpscalerContext)context;
|
|
await pssrContext.Destroy();
|
|
ContextPool.Enqueue(pssrContext.ContextIndex);
|
|
}
|
|
|
|
public override bool GetRenderResolutionFromQualityMode(FSR2Quality qualityMode, uint displayWidth, uint displayHeight, out uint renderWidth, out uint renderHeight)
|
|
{
|
|
float ratio = GetUpscaleRatioFromQualityMode(qualityMode);
|
|
renderWidth = (uint)Mathf.RoundToInt(displayWidth / ratio);
|
|
renderHeight = (uint)Mathf.RoundToInt(displayHeight / ratio);
|
|
return true;
|
|
}
|
|
|
|
public override float GetUpscaleRatioFromQualityMode(FSR2Quality qualityMode)
|
|
{
|
|
return qualityMode switch
|
|
{
|
|
FSR2Quality.Quality => 1.5f,
|
|
FSR2Quality.Balanced => 1.7f,
|
|
FSR2Quality.Performance => 2.0f,
|
|
FSR2Quality.UltraPerformance => 3.0f,
|
|
_ => 1.0f
|
|
};
|
|
}
|
|
}
|
|
|
|
public class PSSRUpscalerContext : UpscalerContext
|
|
{
|
|
private FSR2CommandInitializationData _initData;
|
|
private uint _contextIndex;
|
|
public uint ContextIndex => _contextIndex;
|
|
|
|
private Texture2D _outputColor;
|
|
|
|
private readonly PSSRPlugin.NativeData<PSSRPlugin.DispatchParams> _dispatchParams = new();
|
|
private readonly PSSRPlugin.NativeData<PSSRPlugin.DestroyParams> _destroyParams = new();
|
|
private readonly PSSRPlugin.NativeData<PSSRPlugin.CaptureParams> _captureParams = new();
|
|
|
|
private bool _initialized;
|
|
|
|
internal void Init(in FSR2CommandInitializationData initSettings, uint contextIndex)
|
|
{
|
|
_initData = initSettings;
|
|
_contextIndex = contextIndex;
|
|
|
|
PSSRPlugin.InitParams initParams;
|
|
initParams.contextIndex = _contextIndex;
|
|
initParams.displayWidth = initSettings.displaySizeWidth;
|
|
initParams.displayHeight = initSettings.displaySizeHeight;
|
|
initParams.maxRenderWidth = initSettings.maxRenderSizeWidth;
|
|
initParams.maxRenderHeight = initSettings.maxRenderSizeHeight;
|
|
initParams.autoKeepCopies = 1u; // Allow native MFSR context to manage previous frame copies for us
|
|
|
|
if (PSSRPlugin.CreateContext(ref initParams, out IntPtr outputColorTexturePtr) >= 0 && outputColorTexturePtr != IntPtr.Zero)
|
|
{
|
|
// PSSR requires an output color texture in a very particular format (k11_11_10Float with kStandard256B tile mode and a specific alignment) that Unity cannot create directly.
|
|
// So instead we let the plugin create that texture and then import it into Unity as a generic 32bpp texture from a native pointer.
|
|
_outputColor = Texture2D.CreateExternalTexture((int)initSettings.displaySizeWidth, (int)initSettings.displaySizeHeight, TextureFormat.RGBA32, false, true, outputColorTexturePtr);
|
|
_dispatchParams.Initialize();
|
|
_destroyParams.Initialize();
|
|
_captureParams.Initialize();
|
|
|
|
_initialized = true;
|
|
}
|
|
}
|
|
|
|
internal async Awaitable Destroy()
|
|
{
|
|
// Wait until the GPU is done with the PSSR context before destroying it
|
|
await Awaitable.EndOfFrameAsync();
|
|
|
|
if (_initialized)
|
|
{
|
|
PSSRPlugin.DestroyContext(_contextIndex);
|
|
_initialized = false;
|
|
}
|
|
|
|
if (_outputColor != null)
|
|
{
|
|
Object.Destroy(_outputColor);
|
|
_outputColor = null;
|
|
}
|
|
|
|
_captureParams.Destroy();
|
|
_destroyParams.Destroy();
|
|
_dispatchParams.Destroy();
|
|
}
|
|
|
|
public override void Execute(CommandBuffer cmd, in FSR2CommandExecutionData executeData, in FSR2TextureTable textures)
|
|
{
|
|
if (!_initialized || executeData.renderSizeWidth < _initData.displaySizeWidth / 3 || executeData.renderSizeHeight < _initData.displaySizeHeight / 3)
|
|
{
|
|
cmd.Blit(textures.colorInput, textures.colorOutput);
|
|
return;
|
|
}
|
|
|
|
cmd.BeginSample("PSSR");
|
|
|
|
var flags = PSSRPlugin.OptionFlags.None;
|
|
if ((_initData.ffxFsrFlags & FfxFsr2InitializationFlags.DepthInverted) != 0) flags |= PSSRPlugin.OptionFlags.ReverseDepth;
|
|
if ((_initData.ffxFsrFlags & FfxFsr2InitializationFlags.EnableAutoExposure) != 0) flags |= PSSRPlugin.OptionFlags.AutoExposure;
|
|
|
|
ref var dispatchParams = ref _dispatchParams.Value;
|
|
dispatchParams.contextIndex = _contextIndex;
|
|
|
|
dispatchParams.color = ToNativePtr(textures.colorInput);
|
|
dispatchParams.depth = ToNativePtr(textures.depth);
|
|
dispatchParams.prevDepth = IntPtr.Zero; // Native MFSR context will manage previous frame copies internally
|
|
dispatchParams.motionVectors = ToNativePtr(textures.motionVectors);
|
|
dispatchParams.prevMotionVectors = IntPtr.Zero; // Native MFSR context will manage previous frame copies internally
|
|
dispatchParams.exposure = ToNativePtr(textures.exposureTexture);
|
|
dispatchParams.reactiveMask = ToNativePtr(textures.biasColorMask);
|
|
dispatchParams.outputColor = ToNativePtr(_outputColor); // This is a specially prepared texture in the exact format that MFSR requires
|
|
|
|
Matrix4x4 cameraViewMatrix = executeData.cameraViewMatrix;
|
|
Vector4 cameraPosition = cameraViewMatrix.GetColumn(3);
|
|
|
|
dispatchParams.renderWidth = executeData.renderSizeWidth;
|
|
dispatchParams.renderHeight = executeData.renderSizeHeight;
|
|
dispatchParams.jitter = new Vector2(executeData.jitterOffsetX, executeData.jitterOffsetY);
|
|
dispatchParams.motionVectorScale = new Vector2(executeData.MVScaleX, executeData.MVScaleY);
|
|
dispatchParams.camProjectionNoJitter = executeData.cameraProjectionMatrixNoJitter;
|
|
dispatchParams.camForward = -cameraViewMatrix.GetColumn(2);
|
|
dispatchParams.camUp = cameraViewMatrix.GetColumn(1);
|
|
dispatchParams.camRight = cameraViewMatrix.GetColumn(0);
|
|
dispatchParams.camPositionX = cameraPosition.x;
|
|
dispatchParams.camPositionY = cameraPosition.y;
|
|
dispatchParams.camPositionZ = cameraPosition.z;
|
|
dispatchParams.camNear = executeData.cameraNear;
|
|
dispatchParams.camFar = executeData.cameraFar;
|
|
dispatchParams.preExposure = executeData.preExposure;
|
|
dispatchParams.resetHistory = (uint)executeData.reset;
|
|
dispatchParams.flags = flags;
|
|
|
|
PSSRPlugin.IssuePluginEvent(cmd, PSSRPlugin.Event.Dispatch, _dispatchParams);
|
|
|
|
{
|
|
// Convert the PSSR output from R11G11B10 to the expected destination format
|
|
Vector4 scaleBias = new Vector4((float)textures.colorOutput.width / _initData.displaySizeWidth, (float)textures.colorOutput.height / _initData.displaySizeHeight, 0, 0);
|
|
cmd.SetRenderTarget(textures.colorOutput);
|
|
Blitter.BlitColorAndDepth(cmd, _outputColor, null, scaleBias, 0, false);
|
|
}
|
|
|
|
cmd.EndSample("PSSR");
|
|
}
|
|
|
|
private static IntPtr ToNativePtr(Texture texture)
|
|
{
|
|
return texture != null ? texture.GetNativeTexturePtr() : IntPtr.Zero;
|
|
}
|
|
}
|
|
}
|
|
#endif // UNITY_PS5
|