diff --git a/FSR3UnityPlugin.cpp b/FSR3UnityPlugin.cpp index 17a44cd..5c2c378 100644 --- a/FSR3UnityPlugin.cpp +++ b/FSR3UnityPlugin.cpp @@ -703,7 +703,7 @@ static void UNITY_INTERFACE_API OnSetTextureEvent(int eventID, void* data) } else if (s_GraphicsVulkan != nullptr) { - VkAccessFlags accessFlags = (textureSlot == FSR3Textures::tColorOutput) ? VK_ACCESS_SHADER_WRITE_BIT : VK_ACCESS_SHADER_READ_BIT; + VkAccessFlags accessFlags = (textureSlot == FSR3Texture::tColorOutput) ? VK_ACCESS_SHADER_WRITE_BIT : VK_ACCESS_SHADER_READ_BIT; UnityVulkanImage image; if (s_GraphicsVulkan->AccessTextureByID((UnityTextureID)params->textureID, UnityVulkanWholeImage, diff --git a/FSR3UnityPlugin.vcxproj b/FSR3UnityPlugin.vcxproj index 9227741..2db3e3b 100644 --- a/FSR3UnityPlugin.vcxproj +++ b/FSR3UnityPlugin.vcxproj @@ -153,11 +153,13 @@ + + diff --git a/FSR3UnityPlugin.vcxproj.filters b/FSR3UnityPlugin.vcxproj.filters index 5f054da..5f71fbd 100644 --- a/FSR3UnityPlugin.vcxproj.filters +++ b/FSR3UnityPlugin.vcxproj.filters @@ -21,6 +21,9 @@ Source Files + + Source Files + @@ -35,5 +38,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/FSR3UnityTypes.h b/FSR3UnityTypes.h index 0e64eca..4f0a463 100644 --- a/FSR3UnityTypes.h +++ b/FSR3UnityTypes.h @@ -16,7 +16,7 @@ enum FSR3Quality: int32_t qUltraPerformance }; -enum FSR3Textures: int32_t +enum FSR3Texture: int32_t { tColorInput, tColorOutput, diff --git a/FSR3Upscaler_DX12.cpp b/FSR3Upscaler_DX12.cpp index 6dfd6d8..ce4e790 100644 --- a/FSR3Upscaler_DX12.cpp +++ b/FSR3Upscaler_DX12.cpp @@ -25,9 +25,9 @@ bool FSR3Upscaler_DX12::InitFeature(FSR3Feature_FFX& feature, const FSR3CommandI return FFX_API_RETURN_OK == m_ffxFunctions.CreateContext(&feature.upscalingContext, ffx::LinkHeaders(createUpscaling.header, m_DX12BackendDesc.header), nullptr); } -void FSR3Upscaler_DX12::SetTexture(FSR3TextureDesc* textureDesc, UnityTextureID textureID) +void FSR3Upscaler_DX12::SetTexture(FSR3Texture textureType, UnityTextureID textureID, const UnityRenderingExtTextureUpdateParamsV2* params, FSR3TextureDesc* outTextureDesc) { - textureDesc->image = (intptr_t)m_GraphicsDevice->TextureFromNativeTexture(textureID); + outTextureDesc->image = (intptr_t)m_GraphicsDevice->TextureFromNativeTexture(textureID); } void FSR3Upscaler_DX12::Execute(FSR3Feature_FFX& feature, const FSR3CommandExecutionData* execData) @@ -81,11 +81,6 @@ void FSR3Upscaler_DX12::Execute(FSR3Feature_FFX& feature, const FSR3CommandExecu m_ffxFunctions.Dispatch(&feature.upscalingContext, &dispatchUpscale.header); } -bool FSR3Upscaler_DX12::IsValidFeature(FSR3Feature_FFX& feature) -{ - return feature.upscalingContext != nullptr; -} - void FSR3Upscaler_DX12::AwaitEndOfFrame(uint64_t frameValue) { // 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. @@ -97,11 +92,6 @@ void FSR3Upscaler_DX12::AwaitEndOfFrame(uint64_t frameValue) } } -void FSR3Upscaler_DX12::DestroyContext(FSR3Feature_FFX& feature) -{ - m_ffxFunctions.DestroyContext(&feature.upscalingContext, nullptr); -} - void FSR3Upscaler_DX12::DoShutdown() { FSR3Upscaler_FFXBase::DoShutdown(); diff --git a/FSR3Upscaler_DX12.h b/FSR3Upscaler_DX12.h index e82cdc7..9fdc70b 100644 --- a/FSR3Upscaler_DX12.h +++ b/FSR3Upscaler_DX12.h @@ -18,15 +18,11 @@ public: bool Init() override; protected: - bool IsValidFeature(FSR3Feature_FFX& feature) override; - bool InitFeature(FSR3Feature_FFX& feature, const FSR3CommandInitializationData* initData) override; - void SetTexture(FSR3TextureDesc* textureDesc, UnityTextureID textureID) override; + void SetTexture(FSR3Texture textureType, UnityTextureID textureID, const UnityRenderingExtTextureUpdateParamsV2* params, FSR3TextureDesc* outTextureDesc) override; void Execute(FSR3Feature_FFX& feature, const FSR3CommandExecutionData* execData) override; void AwaitEndOfFrame(uint64_t frameValue) override; - void DestroyContext(FSR3Feature_FFX& feature) override; - void DoShutdown() override; private: diff --git a/FSR3Upscaler_FFXBase.h b/FSR3Upscaler_FFXBase.h index 5666306..7a85c25 100644 --- a/FSR3Upscaler_FFXBase.h +++ b/FSR3Upscaler_FFXBase.h @@ -77,6 +77,16 @@ protected: return true; } + bool IsValidFeature(FSR3Feature_FFX& feature) override + { + return feature.upscalingContext != nullptr; + } + + void DestroyContext(FSR3Feature_FFX& feature) override + { + m_ffxFunctions.DestroyContext(&feature.upscalingContext, nullptr); + } + void DoShutdown() override { if (m_ffxModule != nullptr) diff --git a/FSR3Upscaler_Vulkan.cpp b/FSR3Upscaler_Vulkan.cpp new file mode 100644 index 0000000..cd0b8ce --- /dev/null +++ b/FSR3Upscaler_Vulkan.cpp @@ -0,0 +1,149 @@ +#include "FSR3Upscaler_Vulkan.h" + +static VkInstance s_VulkanInstance; +static PFN_vkGetInstanceProcAddr s_GetInstanceProcAddr; + +static PFN_vkVoidFunction GetVulkanDeviceProcAddr(VkDevice device, const char* pName) +{ + if (s_GetInstanceProcAddr == nullptr) + return nullptr; + + return s_GetInstanceProcAddr(s_VulkanInstance, pName); +} + +bool FSR3Upscaler_Vulkan::Init() +{ + UnityVulkanInstance instance = m_GraphicsDevice->Instance(); + if (instance.device == nullptr) + return false; + + s_VulkanInstance = instance.instance; + s_GetInstanceProcAddr = instance.getInstanceProcAddr; + + m_VulkanBackendDesc.vkDevice = instance.device; + m_VulkanBackendDesc.vkPhysicalDevice = instance.physicalDevice; + m_VulkanBackendDesc.vkDeviceProcAddr = &GetVulkanDeviceProcAddr; + + return LoadFidelityFXLibrary(TEXT("amd_fidelityfx_vk.dll"), nullptr); +} + +bool FSR3Upscaler_Vulkan::InitFeature(FSR3Feature_FFX& feature, const FSR3CommandInitializationData* initData) +{ + ffx::CreateContextDescUpscale createUpscaling; + createUpscaling.maxUpscaleSize = { initData->displaySizeWidth, initData->displaySizeHeight }; + createUpscaling.maxRenderSize = { initData->maxRenderSizeWidth, initData->maxRenderSizeHeight }; + createUpscaling.flags = initData->flags; + + return FFX_API_RETURN_OK == m_ffxFunctions.CreateContext(&feature.upscalingContext, ffx::LinkHeaders(createUpscaling.header, m_VulkanBackendDesc.header), nullptr); +} + +void FSR3Upscaler_Vulkan::SetTexture(FSR3Texture textureType, UnityTextureID textureID, const UnityRenderingExtTextureUpdateParamsV2* params, FSR3TextureDesc* outTextureDesc) +{ + VkAccessFlags accessFlags = (textureType == FSR3Texture::tColorOutput) ? VK_ACCESS_SHADER_WRITE_BIT : VK_ACCESS_SHADER_READ_BIT; + + UnityVulkanImage image; + if (m_GraphicsDevice->AccessTextureByID(textureID, UnityVulkanWholeImage, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, accessFlags, + kUnityVulkanResourceAccess_PipelineBarrier, &image)) + { + outTextureDesc->image = (intptr_t)image.image; + outTextureDesc->width = params->width; + outTextureDesc->height = params->height; + outTextureDesc->format = (uint32_t)image.format; + } + else + { + outTextureDesc->image = 0; + } +} + +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); +} + +void FSR3Upscaler_Vulkan::Execute(FSR3Feature_FFX& feature, const FSR3CommandExecutionData* execData) +{ + ffx::DispatchDescUpscale dispatchUpscale{}; + + UnityVulkanRecordingState state; + m_GraphicsDevice->CommandRecordingState(&state, kUnityVulkanGraphicsQueueAccess_DontCare); + dispatchUpscale.commandList = state.commandBuffer; + + // Keep track of which frame this dispatch is happening on, so we can verify when it's finished + feature.dispatchFrameValue = state.currentFrameNumber; + + UnityVulkanInstance instance = m_GraphicsDevice->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); + + if (dispatchUpscale.reactive.resource == nullptr) + dispatchUpscale.reactive = GetVulkanTextureResource(instance, feature.textureTable.biasColorMask); + + dispatchUpscale.jitterOffset.x = execData->jitterOffsetX; + dispatchUpscale.jitterOffset.y = execData->jitterOffsetY; + dispatchUpscale.motionVectorScale.x = execData->MVScaleX; + dispatchUpscale.motionVectorScale.y = execData->MVScaleY; + dispatchUpscale.reset = execData->reset; + dispatchUpscale.enableSharpening = execData->enableSharpening; + dispatchUpscale.sharpness = execData->sharpness; + dispatchUpscale.frameTimeDelta = execData->frameTimeDelta; + dispatchUpscale.preExposure = execData->preExposure; + dispatchUpscale.renderSize.width = execData->renderSizeWidth; + dispatchUpscale.renderSize.height = execData->renderSizeHeight; + dispatchUpscale.upscaleSize.width = feature.upscaleSizeWidth; + dispatchUpscale.upscaleSize.height = feature.upscaleSizeHeight; + dispatchUpscale.cameraFovAngleVertical = execData->cameraFovAngleVertical; + + if (feature.flags & FFX_UPSCALE_ENABLE_DEPTH_INVERTED) + { + dispatchUpscale.cameraFar = execData->cameraNear; + dispatchUpscale.cameraNear = execData->cameraFar; + } + else + { + dispatchUpscale.cameraFar = execData->cameraFar; + dispatchUpscale.cameraNear = execData->cameraNear; + } + + m_ffxFunctions.Dispatch(&feature.upscalingContext, &dispatchUpscale.header); +} + +void FSR3Upscaler_Vulkan::AwaitEndOfFrame(uint64_t frameValue) +{ + UnityVulkanRecordingState state; + m_GraphicsDevice->CommandRecordingState(&state, kUnityVulkanGraphicsQueueAccess_DontCare); + if (frameValue > state.safeFrameNumber) + { + UnityVulkanInstance instance = m_GraphicsDevice->Instance(); + vkQueueWaitIdle(instance.graphicsQueue); + } +} + +void FSR3Upscaler_Vulkan::DoShutdown() +{ + FSR3Upscaler_FFXBase::DoShutdown(); + + m_VulkanBackendDesc.vkDevice = nullptr; + m_VulkanBackendDesc.vkPhysicalDevice = nullptr; + m_VulkanBackendDesc.vkDeviceProcAddr = nullptr; +} diff --git a/FSR3Upscaler_Vulkan.h b/FSR3Upscaler_Vulkan.h new file mode 100644 index 0000000..f3eb4f3 --- /dev/null +++ b/FSR3Upscaler_Vulkan.h @@ -0,0 +1,31 @@ +#pragma once +#include "FSR3Upscaler_FFXBase.h" + +#include "ffx_api/ffx_upscale.hpp" +#include "ffx_api/vk/ffx_api_vk.hpp" + +#include "UnityPluginAPI/IUnityGraphicsVulkan.h" + +class FSR3Upscaler_Vulkan : FSR3Upscaler_FFXBase +{ +public: + FSR3Upscaler_Vulkan(IUnityInterfaces* unityInterfaces, IUnityGraphicsVulkan* graphicsDevice) : + FSR3Upscaler_FFXBase(unityInterfaces), + m_GraphicsDevice(graphicsDevice), m_VulkanBackendDesc() + { + } + + bool Init() override; + +protected: + bool InitFeature(FSR3Feature_FFX& feature, const FSR3CommandInitializationData* initData) override; + void SetTexture(FSR3Texture textureType, UnityTextureID textureID, const UnityRenderingExtTextureUpdateParamsV2* params, FSR3TextureDesc* outTextureDesc) override; + void Execute(FSR3Feature_FFX& feature, const FSR3CommandExecutionData* execData) override; + + void AwaitEndOfFrame(uint64_t frameValue) override; + void DoShutdown() override; + +private: + IUnityGraphicsVulkan* m_GraphicsDevice; + ffx::CreateBackendVKDesc m_VulkanBackendDesc; +}; diff --git a/UpscalerGraphicsDevice.h b/UpscalerGraphicsDevice.h index e737d14..b15a08d 100644 --- a/UpscalerGraphicsDevice.h +++ b/UpscalerGraphicsDevice.h @@ -6,6 +6,7 @@ #include #include "UnityPluginAPI/IUnityInterface.h" +#include "UnityPluginAPI/IUnityRenderingExtensions.h" #include "FSR3UnityTypes.h" @@ -87,7 +88,7 @@ public: memset(&m_Features[featureSlot].textureTable, 0, sizeof(FSR3TextureTable)); } - virtual void SetTextureSlot(uint32_t featureSlot, uint32_t textureSlot, UnityTextureID textureID) + virtual void SetTextureSlot(uint32_t featureSlot, uint32_t textureSlot, UnityTextureID textureID, const UnityRenderingExtTextureUpdateParamsV2* params) { if (featureSlot < 0 || featureSlot >= m_Features.size()) return; @@ -95,7 +96,7 @@ public: // 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 FSR3TextureDesc* textureDesc = ((FSR3TextureDesc*)&m_Features[featureSlot].textureTable) + textureSlot; - SetTexture(textureDesc, textureID); + SetTexture((FSR3Texture)textureSlot, textureID, params, textureDesc); } virtual void Execute(const FSR3CommandExecutionData* execData) @@ -132,7 +133,7 @@ protected: virtual bool IsValidFeature(TFeature& feature) = 0; virtual bool InitFeature(TFeature& feature, const FSR3CommandInitializationData* initData) = 0; - virtual void SetTexture(FSR3TextureDesc* textureDesc, UnityTextureID textureID) = 0; + virtual void SetTexture(FSR3Texture textureType, UnityTextureID textureID, const UnityRenderingExtTextureUpdateParamsV2* params, FSR3TextureDesc* outTextureDesc) = 0; virtual void Execute(TFeature& feature, const FSR3CommandExecutionData* execData) = 0; virtual void PostExecute(TFeature& feature, const FSR3CommandExecutionData* execData) { }