@ -50,6 +50,8 @@ struct FSR3Feature
uint32_t upscaleSizeHeight ;
uint32_t upscaleSizeHeight ;
uint32_t flags ;
uint32_t flags ;
uint64_t dispatchFrameValue ;
FSR3TextureTable textureTable ;
FSR3TextureTable textureTable ;
} ;
} ;
@ -65,6 +67,8 @@ static ffx::CreateBackendVKDesc s_VulkanBackendDesc{};
static FfxDevice s_DX11Device = nullptr ;
static FfxDevice s_DX11Device = nullptr ;
static FfxFsr2Interface s_Fsr2Interface ;
static FfxFsr2Interface s_Fsr2Interface ;
static HANDLE s_FrameFenceEventHandle = nullptr ;
// Unity plugin load event
// Unity plugin load event
extern " C " void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad ( IUnityInterfaces * unityInterfaces )
extern " C " void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad ( IUnityInterfaces * unityInterfaces )
{
{
@ -221,6 +225,7 @@ extern "C" bool UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_InitApi()
return false ;
return false ;
s_DX12BackendDesc . device = device ;
s_DX12BackendDesc . device = device ;
s_FrameFenceEventHandle = CreateEventEx ( nullptr , nullptr , 0 , EVENT_ALL_ACCESS ) ;
return LoadFidelityFXLibrary ( TEXT ( " amd_fidelityfx_dx12.dll " ) ) ;
return LoadFidelityFXLibrary ( TEXT ( " amd_fidelityfx_dx12.dll " ) ) ;
}
}
@ -243,6 +248,19 @@ extern "C" bool UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_InitApi()
static void DestroyFeature ( uint32_t featureSlot )
static void DestroyFeature ( uint32_t featureSlot )
{
{
auto & feature = s_Features [ featureSlot ] ;
auto & feature = s_Features [ featureSlot ] ;
if ( s_GraphicsD3D12 ! = nullptr )
{
// If there's still an upscale dispatch executing on the current frame, wait until rendering is finished before destroying its context.
// Thanks to https://alextardif.com/D3D11To12P1.html for explaining how fences work and how to make the CPU wait for a command queue to complete.
ID3D12Fence * frameFence = s_GraphicsD3D12 - > GetFrameFence ( ) ;
if ( feature . dispatchFrameValue > frameFence - > GetCompletedValue ( ) )
{
frameFence - > SetEventOnCompletion ( feature . dispatchFrameValue , s_FrameFenceEventHandle ) ;
WaitForSingleObjectEx ( s_FrameFenceEventHandle , INFINITE , false ) ;
}
}
if ( feature . upscalingContext ! = nullptr )
if ( feature . upscalingContext ! = nullptr )
{
{
s_ffxFunctions . DestroyContext ( & feature . upscalingContext , nullptr ) ;
s_ffxFunctions . DestroyContext ( & feature . upscalingContext , nullptr ) ;
@ -276,6 +294,12 @@ extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_ShutdownApi()
s_Fsr2Interface . scratchBuffer = nullptr ;
s_Fsr2Interface . scratchBuffer = nullptr ;
}
}
if ( s_FrameFenceEventHandle ! = nullptr )
{
CloseHandle ( s_FrameFenceEventHandle ) ;
s_FrameFenceEventHandle = nullptr ;
}
s_VulkanBackendDesc . vkDevice = nullptr ;
s_VulkanBackendDesc . vkDevice = nullptr ;
s_VulkanBackendDesc . vkPhysicalDevice = nullptr ;
s_VulkanBackendDesc . vkPhysicalDevice = nullptr ;
s_VulkanBackendDesc . vkDeviceProcAddr = nullptr ;
s_VulkanBackendDesc . vkDeviceProcAddr = nullptr ;
@ -442,6 +466,9 @@ static void UNITY_INTERFACE_API OnRenderEventAndData(int eventID, void* data)
s_GraphicsD3D12 - > CommandRecordingState ( & state ) ;
s_GraphicsD3D12 - > CommandRecordingState ( & state ) ;
dispatchUpscale . commandList = state . commandList ;
dispatchUpscale . commandList = state . commandList ;
// Keep track of which frame this dispatch is happening on, so we can verify when it's finished
feature . dispatchFrameValue = s_GraphicsD3D12 - > GetNextFrameFenceValue ( ) ;
dispatchUpscale . color = ffxApiGetResourceDX12 ( ( ID3D12Resource * ) feature . textureTable . colorInput . image , FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ ) ;
dispatchUpscale . color = ffxApiGetResourceDX12 ( ( ID3D12Resource * ) feature . textureTable . colorInput . image , FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ ) ;
dispatchUpscale . depth = ffxApiGetResourceDX12 ( ( ID3D12Resource * ) feature . textureTable . depth . image , FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ ) ;
dispatchUpscale . depth = ffxApiGetResourceDX12 ( ( ID3D12Resource * ) feature . textureTable . depth . image , FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ ) ;
dispatchUpscale . motionVectors = ffxApiGetResourceDX12 ( ( ID3D12Resource * ) feature . textureTable . motionVectors . image , FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ ) ;
dispatchUpscale . motionVectors = ffxApiGetResourceDX12 ( ( ID3D12Resource * ) feature . textureTable . motionVectors . image , FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ ) ;
@ -456,6 +483,9 @@ static void UNITY_INTERFACE_API OnRenderEventAndData(int eventID, void* data)
s_GraphicsVulkan - > CommandRecordingState ( & state , kUnityVulkanGraphicsQueueAccess_DontCare ) ;
s_GraphicsVulkan - > CommandRecordingState ( & state , kUnityVulkanGraphicsQueueAccess_DontCare ) ;
dispatchUpscale . commandList = state . commandBuffer ;
dispatchUpscale . commandList = state . commandBuffer ;
// TODO: probably need to make use of state.currentFrameNumber and state.safeFrameNumber to keep track of when it's safe to destroy the upscaling context
feature . dispatchFrameValue = state . currentFrameNumber ;
UnityVulkanInstance instance = s_GraphicsVulkan - > Instance ( ) ;
UnityVulkanInstance instance = s_GraphicsVulkan - > Instance ( ) ;
dispatchUpscale . color = GetVulkanTextureResource ( instance , feature . textureTable . colorInput ) ;
dispatchUpscale . color = GetVulkanTextureResource ( instance , feature . textureTable . colorInput ) ;
dispatchUpscale . depth = GetVulkanTextureResource ( instance , feature . textureTable . depth ) ;
dispatchUpscale . depth = GetVulkanTextureResource ( instance , feature . textureTable . depth ) ;