diff --git a/FSR3UnityPlugin.cpp b/FSR3UnityPlugin.cpp index 5c10dfd..1a71137 100644 --- a/FSR3UnityPlugin.cpp +++ b/FSR3UnityPlugin.cpp @@ -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 s_Features; static std::queue 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; - - s_GraphicsD3D12 = s_UnityInterfaces->Get(); - if (s_GraphicsD3D12 == nullptr) + switch (s_RendererType) { - UNITY_LOG_ERROR(s_Log, "Could not obtain D3D12 Graphics interface!"); - return; + case kUnityGfxRendererD3D12: + { + s_GraphicsD3D12 = s_UnityInterfaces->Get(); + if (s_GraphicsD3D12 == nullptr) + { + UNITY_LOG_ERROR(s_Log, "Could not obtain D3D12 Graphics interface!"); + return; + } + break; + } + case kUnityGfxRendererVulkan: + { + s_GraphicsVulkan = s_UnityInterfaces->Get(); + 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,17 +150,36 @@ static void FreeFeatureSlot(uint32_t featureSlot) memset(&s_Features[featureSlot], 0, sizeof(FSR3Feature)); } +static PFN_vkVoidFunction GetVulkanDeviceProcAddr(VkDevice device, const char* pName) +{ + 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) - return false; + if (s_GraphicsD3D12 != nullptr) + { + ID3D12Device* device = s_GraphicsD3D12->GetDevice(); + if (device == nullptr) + return false; - ID3D12Device* device = s_GraphicsD3D12->GetDevice(); - if (device == nullptr) - return false; + 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; + } - s_BackendDesc.device = device; - return true; + return false; } extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_ShutdownApi() @@ -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]; - 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); + if (s_GraphicsD3D12 != nullptr) + { + UnityGraphicsD3D12RecordingState state; + s_GraphicsD3D12->CommandRecordingState(&state); + dispatchUpscale.commandList = state.commandList; + + 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; } } diff --git a/FSR3UnityTypes.h b/FSR3UnityTypes.h index 6c62e12..b72993b 100644 --- a/FSR3UnityTypes.h +++ b/FSR3UnityTypes.h @@ -59,16 +59,25 @@ struct FSR3CommandExecutionData uint32_t featureSlot; }; +struct FSR3TextureDesc +{ + intptr_t image; + + uint32_t width; + uint32_t height; + uint32_t format; +}; + struct FSR3TextureTable { - intptr_t colorInput; - intptr_t colorOutput; - intptr_t depth; - intptr_t motionVectors; - intptr_t transparencyMask; - intptr_t exposureTexture; - intptr_t reactiveMask; - intptr_t biasColorMask; + FSR3TextureDesc colorInput; + FSR3TextureDesc colorOutput; + FSR3TextureDesc depth; + FSR3TextureDesc motionVectors; + FSR3TextureDesc transparencyMask; + FSR3TextureDesc exposureTexture; + FSR3TextureDesc reactiveMask; + FSR3TextureDesc biasColorMask; uint32_t featureSlot; };