@ -26,6 +26,7 @@ static IUnityInterfaces* s_UnityInterfaces = nullptr;
static IUnityLog * s_Log = nullptr ;
static IUnityGraphics * s_Graphics = nullptr ;
static IUnityGraphicsD3D12v7 * s_GraphicsD3D12 = nullptr ;
static IUnityGraphicsVulkan * s_GraphicsVulkan = nullptr ;
static UnityGfxRenderer s_RendererType = kUnityGfxRendererNull ;
static void UNITY_INTERFACE_API OnGraphicsDeviceEvent ( UnityGfxDeviceEventType eventType ) ;
@ -47,7 +48,8 @@ static std::vector<FSR3Feature> s_Features;
static std : : queue < uint32_t > s_FeatureSlots ;
static std : : mutex s_FeatureMutex ;
static ffx : : CreateBackendDX12Desc s_BackendDesc { } ;
static ffx : : CreateBackendDX12Desc s_DX12BackendDesc { } ;
static ffx : : CreateBackendVKDesc s_VulkanBackendDesc { } ;
// Unity plugin load event
extern " C " void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad ( IUnityInterfaces * unityInterfaces )
@ -76,20 +78,35 @@ static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType ev
case kUnityGfxDeviceEventInitialize :
{
s_RendererType = s_Graphics - > GetRenderer ( ) ;
if ( s_RendererType ! = kUnityGfxRendererD3D12 )
return ;
switch ( s_RendererType )
{
case kUnityGfxRendererD3D12 :
{
s_GraphicsD3D12 = s_UnityInterfaces - > Get < IUnityGraphicsD3D12v7 > ( ) ;
if ( s_GraphicsD3D12 = = nullptr )
{
UNITY_LOG_ERROR ( s_Log , " Could not obtain D3D12 Graphics interface! " ) ;
return ;
}
break ;
}
case kUnityGfxRendererVulkan :
{
s_GraphicsVulkan = s_UnityInterfaces - > Get < IUnityGraphicsVulkan > ( ) ;
if ( s_GraphicsVulkan = = nullptr )
{
UNITY_LOG_ERROR ( s_Log , " Could not obtain Vulkan Graphics interface! " ) ;
return ;
}
break ;
}
}
break ;
}
case kUnityGfxDeviceEventShutdown :
{
s_GraphicsVulkan = nullptr ;
s_GraphicsD3D12 = nullptr ;
s_RendererType = kUnityGfxRendererNull ;
break ;
@ -133,19 +150,38 @@ static void FreeFeatureSlot(uint32_t featureSlot)
memset ( & s_Features [ featureSlot ] , 0 , sizeof ( FSR3Feature ) ) ;
}
extern " C " bool UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_InitApi ( )
static PFN_vkVoidFunction GetVulkanDeviceProcAddr ( VkDevice device , const char * pName )
{
if ( s_GraphicsD3D12 = = nullptr )
return false ;
UnityVulkanInstance instance = s_GraphicsVulkan - > Instance ( ) ;
return instance . getInstanceProcAddr ( instance . instance , pName ) ;
}
extern " C " bool UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_InitApi ( )
{
if ( s_GraphicsD3D12 ! = nullptr )
{
ID3D12Device * device = s_GraphicsD3D12 - > GetDevice ( ) ;
if ( device = = nullptr )
return false ;
s_BackendDesc . device = device ;
s_DX12BackendDesc . device = device ;
return true ;
}
else if ( s_GraphicsVulkan ! = nullptr )
{
UnityVulkanInstance instance = s_GraphicsVulkan - > Instance ( ) ;
if ( instance . device = = nullptr )
return false ;
s_VulkanBackendDesc . vkDevice = instance . device ;
s_VulkanBackendDesc . vkPhysicalDevice = instance . physicalDevice ;
s_VulkanBackendDesc . vkDeviceProcAddr = & GetVulkanDeviceProcAddr ;
return true ;
}
return false ;
}
extern " C " void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_ShutdownApi ( )
{
for ( uint32_t slot = 0 ; slot < s_Features . size ( ) ; + + slot )
@ -158,7 +194,11 @@ extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_ShutdownApi()
}
}
s_BackendDesc . device = nullptr ;
s_VulkanBackendDesc . vkDevice = nullptr ;
s_VulkanBackendDesc . vkPhysicalDevice = nullptr ;
s_VulkanBackendDesc . vkDeviceProcAddr = nullptr ;
s_DX12BackendDesc . device = nullptr ;
}
extern " C " uint32_t UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_GetDeviceVersion ( )
@ -214,12 +254,28 @@ extern "C" int32_t UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_GetBaseEvent
return BaseEventId ;
}
static FfxApiResource GetVulkanTextureResource ( UnityVulkanInstance & instance , FSR3TextureDesc & texture , FfxApiResourceState state = FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ )
{
FfxApiResourceDescription desc { } ;
if ( texture . image ! = 0 )
{
desc . type = FFX_API_RESOURCE_TYPE_TEXTURE2D ;
desc . format = ffxApiGetSurfaceFormatVK ( ( VkFormat ) texture . format ) ;
desc . width = texture . width ;
desc . height = texture . height ;
desc . depth = 1 ;
desc . mipCount = 1 ;
desc . flags = FFX_API_RESOURCE_FLAGS_NONE ;
desc . usage = state = = FFX_API_RESOURCE_STATE_UNORDERED_ACCESS ? FFX_API_RESOURCE_USAGE_UAV : FFX_API_RESOURCE_USAGE_READ_ONLY ;
}
return ffxApiGetResourceVK ( ( void * ) texture . image , desc , state ) ;
}
// Plugin function to handle a specific rendering event
static void UNITY_INTERFACE_API OnRenderEventAndData ( int eventID , void * data )
{
if ( s_GraphicsD3D12 = = nullptr | | s_BackendDesc . device = = nullptr )
return ;
// User rendering code
switch ( eventID )
{
@ -245,19 +301,37 @@ static void UNITY_INTERFACE_API OnRenderEventAndData(int eventID, void* data)
auto & feature = s_Features [ params - > featureSlot ] ;
ffx : : DispatchDescUpscale dispatchUpscale { } ;
if ( s_GraphicsD3D12 ! = nullptr )
{
UnityGraphicsD3D12RecordingState state ;
s_GraphicsD3D12 - > CommandRecordingState ( & state ) ;
ffx : : DispatchDescUpscale dispatchUpscale { } ;
dispatchUpscale . commandList = state . commandList ;
dispatchUpscale . color = ffxApiGetResourceDX12 ( ( ID3D12Resource * ) feature . textureTable . colorInput , FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ ) ;
dispatchUpscale . depth = ffxApiGetResourceDX12 ( ( ID3D12Resource * ) feature . textureTable . depth , FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ ) ;
dispatchUpscale . motionVectors = ffxApiGetResourceDX12 ( ( ID3D12Resource * ) feature . textureTable . motionVectors , FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ ) ;
dispatchUpscale . exposure = ffxApiGetResourceDX12 ( ( ID3D12Resource * ) feature . textureTable . exposureTexture , FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ ) ;
dispatchUpscale . reactive = ffxApiGetResourceDX12 ( ( ID3D12Resource * ) feature . textureTable . reactiveMask , FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ ) ;
dispatchUpscale . transparencyAndComposition = ffxApiGetResourceDX12 ( ( ID3D12Resource * ) feature . textureTable . transparencyMask , FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ ) ;
dispatchUpscale . output = ffxApiGetResourceDX12 ( ( ID3D12Resource * ) feature . textureTable . colorOutput , FFX_API_RESOURCE_STATE_UNORDERED_ACCESS ) ;
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 . motionVectors = ffxApiGetResourceDX12 ( ( ID3D12Resource * ) feature . textureTable . motionVectors . image , FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ ) ;
dispatchUpscale . exposure = ffxApiGetResourceDX12 ( ( ID3D12Resource * ) feature . textureTable . exposureTexture . image , FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ ) ;
dispatchUpscale . reactive = ffxApiGetResourceDX12 ( ( ID3D12Resource * ) feature . textureTable . reactiveMask . image , FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ ) ;
dispatchUpscale . transparencyAndComposition = ffxApiGetResourceDX12 ( ( ID3D12Resource * ) feature . textureTable . transparencyMask . image , FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ ) ;
dispatchUpscale . output = ffxApiGetResourceDX12 ( ( ID3D12Resource * ) feature . textureTable . colorOutput . image , FFX_API_RESOURCE_STATE_UNORDERED_ACCESS ) ;
}
else if ( s_GraphicsVulkan ! = nullptr )
{
UnityVulkanRecordingState state ;
s_GraphicsVulkan - > CommandRecordingState ( & state , kUnityVulkanGraphicsQueueAccess_DontCare ) ;
dispatchUpscale . commandList = state . commandBuffer ;
UnityVulkanInstance instance = s_GraphicsVulkan - > Instance ( ) ;
dispatchUpscale . color = GetVulkanTextureResource ( instance , feature . textureTable . colorInput ) ;
dispatchUpscale . depth = GetVulkanTextureResource ( instance , feature . textureTable . depth ) ;
dispatchUpscale . motionVectors = GetVulkanTextureResource ( instance , feature . textureTable . motionVectors ) ;
dispatchUpscale . exposure = GetVulkanTextureResource ( instance , feature . textureTable . exposureTexture ) ;
dispatchUpscale . reactive = GetVulkanTextureResource ( instance , feature . textureTable . reactiveMask ) ;
dispatchUpscale . transparencyAndComposition = GetVulkanTextureResource ( instance , feature . textureTable . transparencyMask ) ;
dispatchUpscale . output = GetVulkanTextureResource ( instance , feature . textureTable . colorOutput , FFX_API_RESOURCE_STATE_UNORDERED_ACCESS ) ;
}
dispatchUpscale . jitterOffset . x = params - > jitterOffsetX ;
dispatchUpscale . jitterOffset . y = params - > jitterOffsetY ;
@ -309,7 +383,14 @@ static void UNITY_INTERFACE_API OnRenderEventAndData(int eventID, void* data)
createUpscaling . maxRenderSize = { params - > maxRenderSizeWidth , params - > maxRenderSizeHeight } ;
createUpscaling . flags = params - > flags ;
ffx : : CreateContext ( feature . upscalingContext , nullptr , createUpscaling , s_BackendDesc ) ;
if ( s_GraphicsD3D12 ! = nullptr )
{
ffx : : CreateContext ( feature . upscalingContext , nullptr , createUpscaling , s_DX12BackendDesc ) ;
}
else if ( s_GraphicsVulkan ! = nullptr )
{
ffx : : CreateContext ( feature . upscalingContext , nullptr , createUpscaling , s_VulkanBackendDesc ) ;
}
break ;
}
}
@ -317,9 +398,6 @@ static void UNITY_INTERFACE_API OnRenderEventAndData(int eventID, void* data)
static void UNITY_INTERFACE_API OnSetTextureEvent ( int eventID , void * data )
{
if ( s_GraphicsD3D12 = = nullptr )
return ;
auto * params = ( UnityRenderingExtTextureUpdateParamsV2 * ) data ;
// userData = (featureId & (int) ushort.MaxValue) << 16 | (textureSlot & (int) short.MaxValue) << 1 | (clearTextureTable ? 1 : 0);
@ -347,7 +425,32 @@ static void UNITY_INTERFACE_API OnSetTextureEvent(int eventID, void* data)
{
// We organized the texture table struct to be ordered the same as the texture slot enum
// This way we can use the texture slot value simply as a pointer offset into the texture table
* ( ( ( intptr_t * ) & feature . textureTable ) + textureSlot ) = ( intptr_t ) s_GraphicsD3D12 - > TextureFromNativeTexture ( ( UnityTextureID ) params - > textureID ) ;
FSR3TextureDesc * textureDesc = ( ( FSR3TextureDesc * ) & feature . textureTable ) + textureSlot ;
if ( s_GraphicsD3D12 ! = nullptr )
{
textureDesc - > image = ( intptr_t ) s_GraphicsD3D12 - > TextureFromNativeTexture ( ( UnityTextureID ) params - > textureID ) ;
}
else if ( s_GraphicsVulkan ! = nullptr )
{
VkAccessFlags accessFlags = ( textureSlot = = FSR3Textures : : tColorOutput ) ? VK_ACCESS_SHADER_WRITE_BIT : VK_ACCESS_SHADER_READ_BIT ;
UnityVulkanImage image ;
if ( s_GraphicsVulkan - > AccessTextureByID ( ( UnityTextureID ) params - > textureID , UnityVulkanWholeImage ,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL , VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT , accessFlags ,
kUnityVulkanResourceAccess_PipelineBarrier , & image ) )
{
textureDesc - > image = ( intptr_t ) image . image ;
textureDesc - > width = params - > width ;
textureDesc - > height = params - > height ;
textureDesc - > format = ( uint32_t ) image . format ;
}
else
{
textureDesc - > image = 0 ;
}
}
break ;
}
}