From 49d622a7637fa273bc9b5fe2e7d70957c743f6f9 Mon Sep 17 00:00:00 2001 From: Nico de Poel Date: Wed, 2 Apr 2025 22:00:31 +0200 Subject: [PATCH] Reworked core plugin code to make use of the upscaler classes, fixed some issues along the way --- FSR2Upscaler_DX11.cpp | 4 +- FSR2Upscaler_DX11.h | 7 +- FSR3UnityPlugin.cpp | 554 +++----------------------------- FSR3UnityPlugin.vcxproj | 1 + FSR3UnityPlugin.vcxproj.filters | 3 + FSR3Upscaler_DX12.cpp | 2 +- FSR3Upscaler_DX12.h | 9 +- FSR3Upscaler_FFXBase.h | 7 +- FSR3Upscaler_Vulkan.cpp | 6 +- FSR3Upscaler_Vulkan.h | 9 +- Upscaler.h | 22 ++ UpscalerGraphicsDevice.h | 31 +- 12 files changed, 109 insertions(+), 546 deletions(-) create mode 100644 Upscaler.h diff --git a/FSR2Upscaler_DX11.cpp b/FSR2Upscaler_DX11.cpp index 57dfc72..a27f6df 100644 --- a/FSR2Upscaler_DX11.cpp +++ b/FSR2Upscaler_DX11.cpp @@ -34,9 +34,9 @@ bool FSR2Upscaler_DX11::InitFeature(FSR2Feature& feature, const FSR3CommandIniti return feature.isValid; } -void FSR2Upscaler_DX11::SetTexture(FSR3Texture textureType, UnityTextureID textureID, const UnityRenderingExtTextureUpdateParamsV2* params, FSR3TextureDesc* outTextureDesc) +void FSR2Upscaler_DX11::SetTexture(FSR3Texture textureType, UnityTextureID textureID, uint32_t width, uint32_t height, FSR3TextureDesc* outTextureDesc) { - outTextureDesc->image = (intptr_t)m_GraphicsDevice->TextureFromNativeTexture((UnityTextureID)params->textureID); + outTextureDesc->image = (intptr_t)m_GraphicsDevice->TextureFromNativeTexture(textureID); } void FSR2Upscaler_DX11::Execute(FSR2Feature& feature, const FSR3CommandExecutionData* execData) diff --git a/FSR2Upscaler_DX11.h b/FSR2Upscaler_DX11.h index 956f1e0..62b9ba8 100644 --- a/FSR2Upscaler_DX11.h +++ b/FSR2Upscaler_DX11.h @@ -4,6 +4,7 @@ #include "ffx-fsr2-api/ffx_fsr2.h" #include +#include "UnityPluginAPI/IUnityGraphics.h" #include "UnityPluginAPI/IUnityGraphicsD3D11.h" struct FSR2Feature @@ -20,10 +21,10 @@ struct FSR2Feature FSR3TextureTable textureTable; }; -class FSR2Upscaler_DX11 : UpscalerGraphicsDevice +class FSR2Upscaler_DX11 : public UpscalerGraphicsDevice { public: - FSR2Upscaler_DX11(IUnityInterfaces* unityInterfaces, IUnityGraphicsD3D11* graphicsDevice) : + FSR2Upscaler_DX11(IUnityGraphicsD3D11* graphicsDevice) : m_GraphicsDevice(graphicsDevice), m_DX11Device(nullptr), m_Fsr2Interface() { } @@ -34,7 +35,7 @@ protected: bool IsValidFeature(FSR2Feature& feature); bool InitFeature(FSR2Feature& feature, const FSR3CommandInitializationData* initData); - void SetTexture(FSR3Texture textureType, UnityTextureID textureID, const UnityRenderingExtTextureUpdateParamsV2* params, FSR3TextureDesc* outTextureDesc); + void SetTexture(FSR3Texture textureType, UnityTextureID textureID, uint32_t width, uint32_t height, FSR3TextureDesc* outTextureDesc); void Execute(FSR2Feature& feature, const FSR3CommandExecutionData* execData); void AwaitEndOfFrame(uint64_t frameValue); diff --git a/FSR3UnityPlugin.cpp b/FSR3UnityPlugin.cpp index 5c2c378..127170c 100644 --- a/FSR3UnityPlugin.cpp +++ b/FSR3UnityPlugin.cpp @@ -1,74 +1,26 @@ -#include - -#include -#include -#include -#include +#include "Upscaler.h" #include "UnityPluginAPI/IUnityInterface.h" #include "UnityPluginAPI/IUnityLog.h" #include "UnityPluginAPI/IUnityGraphics.h" #include "UnityPluginAPI/IUnityRenderingExtensions.h" -#include -#include -#include -#include "UnityPluginAPI/IUnityGraphicsD3D11.h" -#include "UnityPluginAPI/IUnityGraphicsD3D12.h" -#include "UnityPluginAPI/IUnityGraphicsVulkan.h" - -#include "ffx_api/ffx_api_loader.h" -#include "ffx_api/ffx_upscale.hpp" -#include "ffx_api/dx12/ffx_api_dx12.hpp" -#include "ffx_api/vk/ffx_api_vk.hpp" - -#include "ffx-fsr2-api/ffx_fsr2.h" -#include "ffx-fsr2-api/dx11/ffx_fsr2_dx11.h" - -#include "FSR3UnityTypes.h" +#include "FSR2Upscaler_DX11.h" +#include "FSR3Upscaler_DX12.h" +#include "FSR3Upscaler_Vulkan.h" static const int32_t BaseEventId = 313; static IUnityInterfaces* s_UnityInterfaces = nullptr; static IUnityLog* s_Log = nullptr; static IUnityGraphics* s_Graphics = nullptr; -static IUnityGraphicsD3D11* s_GraphicsD3D11 = nullptr; -static IUnityGraphicsD3D12v7* s_GraphicsD3D12 = nullptr; -static IUnityGraphicsVulkan* s_GraphicsVulkan = nullptr; static UnityGfxRenderer s_RendererType = kUnityGfxRendererNull; static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType); static void UNITY_INTERFACE_API OnRenderEventAndData(int eventID, void* data); static void UNITY_INTERFACE_API OnSetTextureEvent(int eventID, void* data); -struct FSR3Feature -{ - ffx::Context upscalingContext; - FfxFsr2Context fsr2Context; - bool isValid; - - uint32_t upscaleSizeWidth; - uint32_t upscaleSizeHeight; - uint32_t flags; - - uint64_t dispatchFrameValue; - - FSR3TextureTable textureTable; -}; - -static std::vector s_Features; -static std::queue s_FeatureSlots; -static std::mutex s_FeatureMutex; - -static HMODULE s_ffxModule = nullptr; -static ffxFunctions s_ffxFunctions{}; -static ffx::CreateBackendDX12Desc s_DX12BackendDesc{}; -static ffx::CreateBackendVKDesc s_VulkanBackendDesc{}; - -static FfxDevice s_DX11Device = nullptr; -static FfxFsr2Interface s_Fsr2Interface; - -static HANDLE s_FrameFenceEventHandle = nullptr; +static Upscaler* s_Upscaler = nullptr; // Unity plugin load event extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces) @@ -92,8 +44,6 @@ extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload() static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType) { - std::lock_guard lock(s_FeatureMutex); - switch (eventType) { case kUnityGfxDeviceEventInitialize: @@ -103,44 +53,50 @@ static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType ev { case kUnityGfxRendererD3D11: { - s_GraphicsD3D11 = s_UnityInterfaces->Get(); - if (s_GraphicsD3D11 == nullptr) + auto* graphicsD3D11 = s_UnityInterfaces->Get(); + if (graphicsD3D11 == nullptr) { UNITY_LOG_ERROR(s_Log, "Could not obtain D3D11 Graphics interface!"); return; } + + s_Upscaler = new FSR2Upscaler_DX11(graphicsD3D11); break; } case kUnityGfxRendererD3D12: { - s_GraphicsD3D12 = s_UnityInterfaces->Get(); - if (s_GraphicsD3D12 == nullptr) + auto* graphicsD3D12 = s_UnityInterfaces->Get(); + if (graphicsD3D12 == nullptr) { UNITY_LOG_ERROR(s_Log, "Could not obtain D3D12 Graphics interface!"); return; } + s_Upscaler = new FSR3Upscaler_DX12(s_Log, graphicsD3D12); + UnityD3D12PluginEventConfig eventConfig; eventConfig.graphicsQueueAccess = kUnityD3D12GraphicsQueueAccess_DontCare; eventConfig.flags = kUnityD3D12EventConfigFlag_EnsurePreviousFrameSubmission | kUnityD3D12EventConfigFlag_FlushCommandBuffers | kUnityD3D12EventConfigFlag_SyncWorkerThreads | kUnityD3D12EventConfigFlag_ModifiesCommandBuffersState; eventConfig.ensureActiveRenderTextureIsBound = false; - s_GraphicsD3D12->ConfigureEvent(BaseEventId + FSR3PluginEvent::eExecute, &eventConfig); + graphicsD3D12->ConfigureEvent(BaseEventId + FSR3PluginEvent::eExecute, &eventConfig); break; } case kUnityGfxRendererVulkan: { - s_GraphicsVulkan = s_UnityInterfaces->Get(); - if (s_GraphicsVulkan == nullptr) + auto* graphicsVulkan = s_UnityInterfaces->Get(); + if (graphicsVulkan == nullptr) { UNITY_LOG_ERROR(s_Log, "Could not obtain Vulkan Graphics interface!"); return; } + s_Upscaler = new FSR3Upscaler_Vulkan(s_Log, graphicsVulkan); + UnityVulkanPluginEventConfig eventConfig; eventConfig.graphicsQueueAccess = kUnityVulkanGraphicsQueueAccess_DontCare; eventConfig.flags = kUnityVulkanEventConfigFlag_EnsurePreviousFrameSubmission | kUnityVulkanEventConfigFlag_FlushCommandBuffers | kUnityVulkanEventConfigFlag_SyncWorkerThreads | kUnityVulkanEventConfigFlag_ModifiesCommandBuffersState; eventConfig.renderPassPrecondition = kUnityVulkanRenderPass_EnsureInside; - s_GraphicsVulkan->ConfigureEvent(BaseEventId + FSR3PluginEvent::eExecute, &eventConfig); + graphicsVulkan->ConfigureEvent(BaseEventId + FSR3PluginEvent::eExecute, &eventConfig); break; } } @@ -149,9 +105,12 @@ static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType ev } case kUnityGfxDeviceEventShutdown: { - s_GraphicsVulkan = nullptr; - s_GraphicsD3D12 = nullptr; - s_GraphicsD3D11 = nullptr; + if (s_Upscaler != nullptr) + { + delete s_Upscaler; + s_Upscaler = nullptr; + } + s_RendererType = kUnityGfxRendererNull; break; } @@ -166,222 +125,22 @@ static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType ev }; } -static uint32_t AllocateFeatureSlot() -{ - if (s_FeatureSlots.empty()) - { - // Create a new feature if there are no free slots - uint32_t featureSlot = (uint32_t)s_Features.size(); - s_Features.push_back(std::move(FSR3Feature())); - memset(&s_Features[featureSlot], 0, sizeof(FSR3Feature)); - return featureSlot; - } - - // Reallocate an existing free slot - uint32_t featureSlot = s_FeatureSlots.front(); - s_FeatureSlots.pop(); - return featureSlot; -} - -static void FreeFeatureSlot(uint32_t featureSlot) -{ - // Prevent duplicate free slots - auto& slots = s_FeatureSlots._Get_container(); - if (std::find(slots.begin(), slots.end(), featureSlot) != slots.end()) - return; - - s_FeatureSlots.push(featureSlot); - memset(&s_Features[featureSlot], 0, sizeof(FSR3Feature)); -} - -static bool LoadFidelityFXLibrary(_In_ LPCWSTR lpLibFileName) -{ - s_ffxModule = LoadLibrary(lpLibFileName); - if (s_ffxModule == nullptr) - { - UNITY_LOG_ERROR(s_Log, "Failed to load FidelityFX library!"); - return false; - } - - ffxLoadFunctions(&s_ffxFunctions, s_ffxModule); - if (s_ffxFunctions.CreateContext == nullptr) - { - UNITY_LOG_ERROR(s_Log, "Failed to load FidelityFX library functions!"); - return false; - } - - // Check that we can actually create an upscaler with this library - ffx::QueryDescGetVersions versionQuery{}; - versionQuery.createDescType = FFX_API_CREATE_CONTEXT_DESC_TYPE_UPSCALE; - versionQuery.device = s_DX12BackendDesc.device; - uint64_t versionCount = 0; - versionQuery.outputCount = &versionCount; - s_ffxFunctions.Query(nullptr, &versionQuery.header); - - if (versionCount == 0) - { - UNITY_LOG_ERROR(s_Log, "Failed to load FidelityFX upscaler versions!"); - return false; - } - - // Obtain the default upscaler version and log its name - std::vector versionNames; - std::vector versionIds; - versionIds.resize(versionCount); - versionNames.resize(versionCount); - versionQuery.versionIds = versionIds.data(); - versionQuery.versionNames = versionNames.data(); - s_ffxFunctions.Query(nullptr, &versionQuery.header); - - std::stringstream ss; - ss << "Loaded FidelityFX upscaler: FSR " << versionNames[0]; - UNITY_LOG(s_Log, ss.str().c_str()); - - return true; -} - -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() { - std::lock_guard lock(s_FeatureMutex); - - if (s_GraphicsD3D11 != nullptr) - { - ID3D11Device* device = s_GraphicsD3D11->GetDevice(); - if (device == nullptr) - return false; - - s_DX11Device = ffxGetDeviceDX11(device); - - size_t scratchBufferSize = ffxFsr2GetScratchMemorySizeDX11(); - void* scratchBuffer = malloc(scratchBufferSize); - ffxFsr2GetInterfaceDX11(&s_Fsr2Interface, device, scratchBuffer, scratchBufferSize); - return true; - } - else if (s_GraphicsD3D12 != nullptr) - { - ID3D12Device* device = s_GraphicsD3D12->GetDevice(); - if (device == nullptr) - return false; - - s_DX12BackendDesc.device = device; - s_FrameFenceEventHandle = CreateEventEx(nullptr, nullptr, 0, EVENT_ALL_ACCESS); - - return LoadFidelityFXLibrary(TEXT("amd_fidelityfx_dx12.dll")); - } - else if (s_GraphicsVulkan != nullptr) + if (s_Upscaler != 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 LoadFidelityFXLibrary(TEXT("amd_fidelityfx_vk.dll")); + return s_Upscaler->Init(); } return false; } -static void DestroyFeature(uint32_t featureSlot) -{ - uint64_t dispatchFrameValue = 0; - { - // We need to lock the features list while we're accessing it, but we also can't hold the lock while blocking the main/render thread at the same time. - // Otherwise we're very likely to create a deadlock. So instead we only lock for as long as is necessary to grab the data we need from the feature. - std::lock_guard lock(s_FeatureMutex); - - auto& feature = s_Features[featureSlot]; - if (feature.upscalingContext == nullptr && !feature.isValid) - return; - - dispatchFrameValue = feature.dispatchFrameValue; - } - - 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 (dispatchFrameValue > frameFence->GetCompletedValue()) - { - frameFence->SetEventOnCompletion(dispatchFrameValue, s_FrameFenceEventHandle); - WaitForSingleObjectEx(s_FrameFenceEventHandle, INFINITE, false); - } - } - else if (s_GraphicsVulkan != nullptr) - { - UnityVulkanRecordingState state; - s_GraphicsVulkan->CommandRecordingState(&state, kUnityVulkanGraphicsQueueAccess_DontCare); - if (dispatchFrameValue > state.safeFrameNumber) - { - UnityVulkanInstance instance = s_GraphicsVulkan->Instance(); - vkQueueWaitIdle(instance.graphicsQueue); - } - } - - std::lock_guard lock(s_FeatureMutex); - - auto& feature = s_Features[featureSlot]; - if (feature.upscalingContext != nullptr) - { - s_ffxFunctions.DestroyContext(&feature.upscalingContext, nullptr); - FreeFeatureSlot(featureSlot); - } - else if (feature.isValid) - { - ffxFsr2ContextDestroy(&feature.fsr2Context); - FreeFeatureSlot(featureSlot); - } -} - extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_ShutdownApi() { - size_t numFeatures = 0; - { - std::lock_guard lock(s_FeatureMutex); - numFeatures = s_Features.size(); - } - - for (uint32_t slot = 0; slot < numFeatures; ++slot) - { - DestroyFeature(slot); - } - - std::lock_guard lock(s_FeatureMutex); - - if (s_ffxModule != nullptr) + if (s_Upscaler != nullptr) { - FreeLibrary(s_ffxModule); - s_ffxModule = nullptr; + s_Upscaler->Shutdown(); } - - if (s_Fsr2Interface.scratchBuffer != nullptr) - { - free(s_Fsr2Interface.scratchBuffer); - s_Fsr2Interface.scratchBuffer = nullptr; - } - - if (s_FrameFenceEventHandle != nullptr) - { - CloseHandle(s_FrameFenceEventHandle); - s_FrameFenceEventHandle = nullptr; - } - - s_VulkanBackendDesc.vkDevice = nullptr; - s_VulkanBackendDesc.vkPhysicalDevice = nullptr; - s_VulkanBackendDesc.vkDeviceProcAddr = nullptr; - - s_DX12BackendDesc.device = nullptr; - - s_DX11Device = nullptr; } extern "C" uint32_t UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_GetDeviceVersion() @@ -401,8 +160,12 @@ extern "C" UnityRenderingEventAndData UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API extern "C" uint32_t UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_CreateFeatureSlot() { - std::lock_guard lock(s_FeatureMutex); - return AllocateFeatureSlot(); + if (s_Upscaler != nullptr) + { + s_Upscaler->CreateFeatureSlot(); + } + + return UINT32_MAX; } extern "C" float UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_GetUpscaleRatioFromQualityMode(FSR3Quality qualityMode) @@ -438,29 +201,10 @@ 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_DX11Device == nullptr && s_DX12BackendDesc.device == nullptr && s_VulkanBackendDesc.vkDevice == nullptr) + if (s_Upscaler == nullptr) return; // User rendering code @@ -468,193 +212,26 @@ static void UNITY_INTERFACE_API OnRenderEventAndData(int eventID, void* data) { case BaseEventId + FSR3PluginEvent::eDestroyFeature: { - uint32_t featureSlot = (uint32_t)(int64_t)data; - if (featureSlot < 0 || featureSlot >= s_Features.size()) - return; - - DestroyFeature(featureSlot); + uint32_t featureSlot = (uint32_t)(intptr_t)data; + s_Upscaler->DestroyFeature(featureSlot); break; } case BaseEventId + FSR3PluginEvent::eExecute: { - std::lock_guard lock(s_FeatureMutex); - - auto* params = (FSR3CommandExecutionData*)data; - if (params->featureSlot < 0 || params->featureSlot >= s_Features.size()) - return; - - auto& feature = s_Features[params->featureSlot]; - if (feature.upscalingContext == nullptr && !feature.isValid) - return; - - if (s_GraphicsD3D11 != nullptr) - { - // Execute FSR 2.2 on DX11 - FfxFsr2DispatchDescription dispatchDescription{}; - - ID3D11DeviceContext* ctx = nullptr; - s_GraphicsD3D11->GetDevice()->GetImmediateContext(&ctx); - dispatchDescription.commandList = ctx; - - dispatchDescription.color = ffxGetResourceDX11(&feature.fsr2Context, (ID3D11Resource*)feature.textureTable.colorInput.image); - dispatchDescription.depth = ffxGetResourceDX11(&feature.fsr2Context, (ID3D11Resource*)feature.textureTable.depth.image); - dispatchDescription.motionVectors = ffxGetResourceDX11(&feature.fsr2Context, (ID3D11Resource*)feature.textureTable.motionVectors.image); - dispatchDescription.exposure = ffxGetResourceDX11(&feature.fsr2Context, (ID3D11Resource*)feature.textureTable.exposureTexture.image); - dispatchDescription.reactive = ffxGetResourceDX11(&feature.fsr2Context, (ID3D11Resource*)feature.textureTable.reactiveMask.image); - dispatchDescription.transparencyAndComposition = ffxGetResourceDX11(&feature.fsr2Context, (ID3D11Resource*)feature.textureTable.transparencyMask.image); - dispatchDescription.output = ffxGetResourceDX11(&feature.fsr2Context, (ID3D11Resource*)feature.textureTable.colorOutput.image, nullptr, FFX_RESOURCE_STATE_UNORDERED_ACCESS); - - if (dispatchDescription.reactive.resource == nullptr) - dispatchDescription.reactive = ffxGetResourceDX11(&feature.fsr2Context, (ID3D11Resource*)feature.textureTable.biasColorMask.image); - - dispatchDescription.jitterOffset.x = params->jitterOffsetX; - dispatchDescription.jitterOffset.y = params->jitterOffsetY; - dispatchDescription.motionVectorScale.x = params->MVScaleX; - dispatchDescription.motionVectorScale.y = params->MVScaleY; - dispatchDescription.reset = params->reset; - dispatchDescription.enableSharpening = params->enableSharpening; - dispatchDescription.sharpness = params->sharpness; - dispatchDescription.frameTimeDelta = params->frameTimeDelta; - dispatchDescription.preExposure = params->preExposure; - dispatchDescription.renderSize.width = params->renderSizeWidth; - dispatchDescription.renderSize.height = params->renderSizeHeight; - dispatchDescription.cameraFovAngleVertical = params->cameraFovAngleVertical; - - if (feature.flags & FFX_FSR2_ENABLE_DEPTH_INVERTED) - { - dispatchDescription.cameraFar = params->cameraNear; - dispatchDescription.cameraNear = params->cameraFar; - } - else - { - dispatchDescription.cameraFar = params->cameraFar; - dispatchDescription.cameraNear = params->cameraNear; - } - - ffxFsr2ContextDispatch(&feature.fsr2Context, &dispatchDescription); - return; - } - - // Execute FSR 3.1 or higher on DX12 and Vulkan - ffx::DispatchDescUpscale dispatchUpscale{}; - - if (s_GraphicsD3D12 != nullptr) - { - UnityGraphicsD3D12RecordingState state; - s_GraphicsD3D12->CommandRecordingState(&state); - 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.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); - - if (dispatchUpscale.reactive.resource == nullptr) - dispatchUpscale.reactive = ffxApiGetResourceDX12((ID3D12Resource*)feature.textureTable.biasColorMask.image, FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ); - } - else if (s_GraphicsVulkan != nullptr) - { - UnityVulkanRecordingState state; - s_GraphicsVulkan->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 = 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); - - if (dispatchUpscale.reactive.resource == nullptr) - dispatchUpscale.reactive = GetVulkanTextureResource(instance, feature.textureTable.biasColorMask); - } - - dispatchUpscale.jitterOffset.x = params->jitterOffsetX; - dispatchUpscale.jitterOffset.y = params->jitterOffsetY; - dispatchUpscale.motionVectorScale.x = params->MVScaleX; - dispatchUpscale.motionVectorScale.y = params->MVScaleY; - dispatchUpscale.reset = params->reset; - dispatchUpscale.enableSharpening = params->enableSharpening; - dispatchUpscale.sharpness = params->sharpness; - dispatchUpscale.frameTimeDelta = params->frameTimeDelta; - dispatchUpscale.preExposure = params->preExposure; - dispatchUpscale.renderSize.width = params->renderSizeWidth; - dispatchUpscale.renderSize.height = params->renderSizeHeight; - dispatchUpscale.upscaleSize.width = feature.upscaleSizeWidth; - dispatchUpscale.upscaleSize.height = feature.upscaleSizeHeight; - dispatchUpscale.cameraFovAngleVertical = params->cameraFovAngleVertical; - - if (feature.flags & FFX_UPSCALE_ENABLE_DEPTH_INVERTED) - { - dispatchUpscale.cameraFar = params->cameraNear; - dispatchUpscale.cameraNear = params->cameraFar; - } - else - { - dispatchUpscale.cameraFar = params->cameraFar; - dispatchUpscale.cameraNear = params->cameraNear; - } - - s_ffxFunctions.Dispatch(&feature.upscalingContext, &dispatchUpscale.header); + auto* execData = (FSR3CommandExecutionData*)data; + s_Upscaler->Execute(execData); break; } case BaseEventId + FSR3PluginEvent::ePostExecute: { - auto* params = (FSR3CommandExecutionData*)data; + auto* execData = (FSR3CommandExecutionData*)data; + s_Upscaler->PostExecute(execData); break; } case BaseEventId + FSR3PluginEvent::eInit: { - std::lock_guard lock(s_FeatureMutex); - - auto* params = (FSR3CommandInitializationData*)data; - if (params->featureSlot < 0 || params->featureSlot >= s_Features.size()) - return; - - auto& feature = s_Features[params->featureSlot]; - feature.upscaleSizeWidth = params->displaySizeWidth; - feature.upscaleSizeHeight = params->displaySizeHeight; - feature.flags = params->flags; - - if (s_GraphicsD3D11 != nullptr) - { - // Create an FSR 2.2 context on DX11 - FfxFsr2ContextDescription contextDescription{}; - contextDescription.callbacks = s_Fsr2Interface; - contextDescription.device = s_DX11Device; - contextDescription.displaySize = { params->displaySizeWidth, params->displaySizeHeight }; - contextDescription.maxRenderSize = { params->maxRenderSizeWidth, params->maxRenderSizeHeight }; - contextDescription.flags = params->flags; - - feature.isValid = ffxFsr2ContextCreate(&feature.fsr2Context, &contextDescription) == FFX_OK; - return; - } - - // Create an FSR 3.1 or higher context on DX12 and Vulkan - ffx::CreateContextDescUpscale createUpscaling; - createUpscaling.maxUpscaleSize = { params->displaySizeWidth, params->displaySizeHeight }; - createUpscaling.maxRenderSize = { params->maxRenderSizeWidth, params->maxRenderSizeHeight }; - createUpscaling.flags = params->flags; - - if (s_GraphicsD3D12 != nullptr) - { - s_ffxFunctions.CreateContext(&feature.upscalingContext, ffx::LinkHeaders(createUpscaling.header, s_DX12BackendDesc.header), nullptr); - } - else if (s_GraphicsVulkan != nullptr) - { - s_ffxFunctions.CreateContext(&feature.upscalingContext, ffx::LinkHeaders(createUpscaling.header, s_VulkanBackendDesc.header), nullptr); - } + auto* initData = (FSR3CommandInitializationData*)data; + s_Upscaler->InitFeature(initData); break; } } @@ -662,7 +239,8 @@ static void UNITY_INTERFACE_API OnRenderEventAndData(int eventID, void* data) static void UNITY_INTERFACE_API OnSetTextureEvent(int eventID, void* data) { - std::lock_guard lock(s_FeatureMutex); + if (s_Upscaler == nullptr) + return; auto* params = (UnityRenderingExtTextureUpdateParamsV2*)data; @@ -671,11 +249,6 @@ static void UNITY_INTERFACE_API OnSetTextureEvent(int eventID, void* data) uint32_t textureSlot = (params->userData >> 1) & 0x7FFF; uint32_t clearTextureTable = params->userData & 0x1; - if (featureSlot < 0 || featureSlot >= s_Features.size()) - return; - - auto& feature = s_Features[featureSlot]; - // User rendering code switch (eventID) { @@ -683,44 +256,13 @@ static void UNITY_INTERFACE_API OnSetTextureEvent(int eventID, void* data) { if (clearTextureTable) { - memset(&feature.textureTable, 0, sizeof(FSR3TextureTable)); + s_Upscaler->ClearTextureTable(featureSlot); } break; } case kUnityRenderingExtEventUpdateTextureEndV2: { - // 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*)&feature.textureTable) + textureSlot; - - if (s_GraphicsD3D11 != nullptr) - { - textureDesc->image = (intptr_t)s_GraphicsD3D11->TextureFromNativeTexture((UnityTextureID)params->textureID); - } - else if (s_GraphicsD3D12 != nullptr) - { - textureDesc->image = (intptr_t)s_GraphicsD3D12->TextureFromNativeTexture((UnityTextureID)params->textureID); - } - else if (s_GraphicsVulkan != nullptr) - { - 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, - 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; - } - } - + s_Upscaler->SetTextureSlot(featureSlot, textureSlot, (UnityTextureID)params->textureID, params->width, params->height); break; } } diff --git a/FSR3UnityPlugin.vcxproj b/FSR3UnityPlugin.vcxproj index ac5e4dc..0205df6 100644 --- a/FSR3UnityPlugin.vcxproj +++ b/FSR3UnityPlugin.vcxproj @@ -162,6 +162,7 @@ + diff --git a/FSR3UnityPlugin.vcxproj.filters b/FSR3UnityPlugin.vcxproj.filters index 7d0ac48..20b128b 100644 --- a/FSR3UnityPlugin.vcxproj.filters +++ b/FSR3UnityPlugin.vcxproj.filters @@ -47,5 +47,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/FSR3Upscaler_DX12.cpp b/FSR3Upscaler_DX12.cpp index ce4e790..76b7f33 100644 --- a/FSR3Upscaler_DX12.cpp +++ b/FSR3Upscaler_DX12.cpp @@ -25,7 +25,7 @@ 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(FSR3Texture textureType, UnityTextureID textureID, const UnityRenderingExtTextureUpdateParamsV2* params, FSR3TextureDesc* outTextureDesc) +void FSR3Upscaler_DX12::SetTexture(FSR3Texture textureType, UnityTextureID textureID, uint32_t width, uint32_t height, FSR3TextureDesc* outTextureDesc) { outTextureDesc->image = (intptr_t)m_GraphicsDevice->TextureFromNativeTexture(textureID); } diff --git a/FSR3Upscaler_DX12.h b/FSR3Upscaler_DX12.h index 9fdc70b..7d43662 100644 --- a/FSR3Upscaler_DX12.h +++ b/FSR3Upscaler_DX12.h @@ -4,13 +4,14 @@ #include "ffx_api/ffx_upscale.hpp" #include "ffx_api/dx12/ffx_api_dx12.hpp" +#include "UnityPluginAPI/IUnityGraphics.h" #include "UnityPluginAPI/IUnityGraphicsD3D12.h" -class FSR3Upscaler_DX12 : FSR3Upscaler_FFXBase +class FSR3Upscaler_DX12 : public FSR3Upscaler_FFXBase { public: - FSR3Upscaler_DX12(IUnityInterfaces* unityInterfaces, IUnityGraphicsD3D12v7* graphicsDevice): - FSR3Upscaler_FFXBase(unityInterfaces), + FSR3Upscaler_DX12(IUnityLog* log, IUnityGraphicsD3D12v7* graphicsDevice): + FSR3Upscaler_FFXBase(log), m_GraphicsDevice(graphicsDevice), m_DX12BackendDesc(), m_FrameFenceEventHandle(nullptr) { } @@ -19,7 +20,7 @@ public: protected: bool InitFeature(FSR3Feature_FFX& feature, const FSR3CommandInitializationData* initData) override; - void SetTexture(FSR3Texture textureType, UnityTextureID textureID, const UnityRenderingExtTextureUpdateParamsV2* params, FSR3TextureDesc* outTextureDesc) override; + void SetTexture(FSR3Texture textureType, UnityTextureID textureID, uint32_t width, uint32_t height, FSR3TextureDesc* outTextureDesc) override; void Execute(FSR3Feature_FFX& feature, const FSR3CommandExecutionData* execData) override; void AwaitEndOfFrame(uint64_t frameValue) override; diff --git a/FSR3Upscaler_FFXBase.h b/FSR3Upscaler_FFXBase.h index 7a85c25..9ec177f 100644 --- a/FSR3Upscaler_FFXBase.h +++ b/FSR3Upscaler_FFXBase.h @@ -21,13 +21,12 @@ struct FSR3Feature_FFX FSR3TextureTable textureTable; }; -class FSR3Upscaler_FFXBase : UpscalerGraphicsDevice +class FSR3Upscaler_FFXBase : public UpscalerGraphicsDevice { public: - FSR3Upscaler_FFXBase(IUnityInterfaces* unityInterfaces) - : m_ffxModule(NULL) + FSR3Upscaler_FFXBase(IUnityLog* log) + : m_Log(log), m_ffxModule(NULL) { - m_Log = unityInterfaces->Get(); } protected: diff --git a/FSR3Upscaler_Vulkan.cpp b/FSR3Upscaler_Vulkan.cpp index cd0b8ce..4053d15 100644 --- a/FSR3Upscaler_Vulkan.cpp +++ b/FSR3Upscaler_Vulkan.cpp @@ -37,7 +37,7 @@ bool FSR3Upscaler_Vulkan::InitFeature(FSR3Feature_FFX& feature, const FSR3Comman 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) +void FSR3Upscaler_Vulkan::SetTexture(FSR3Texture textureType, UnityTextureID textureID, uint32_t width, uint32_t height, FSR3TextureDesc* outTextureDesc) { VkAccessFlags accessFlags = (textureType == FSR3Texture::tColorOutput) ? VK_ACCESS_SHADER_WRITE_BIT : VK_ACCESS_SHADER_READ_BIT; @@ -47,8 +47,8 @@ void FSR3Upscaler_Vulkan::SetTexture(FSR3Texture textureType, UnityTextureID tex kUnityVulkanResourceAccess_PipelineBarrier, &image)) { outTextureDesc->image = (intptr_t)image.image; - outTextureDesc->width = params->width; - outTextureDesc->height = params->height; + outTextureDesc->width = width; + outTextureDesc->height = height; outTextureDesc->format = (uint32_t)image.format; } else diff --git a/FSR3Upscaler_Vulkan.h b/FSR3Upscaler_Vulkan.h index f3eb4f3..0210d87 100644 --- a/FSR3Upscaler_Vulkan.h +++ b/FSR3Upscaler_Vulkan.h @@ -4,13 +4,14 @@ #include "ffx_api/ffx_upscale.hpp" #include "ffx_api/vk/ffx_api_vk.hpp" +#include "UnityPluginAPI/IUnityGraphics.h" #include "UnityPluginAPI/IUnityGraphicsVulkan.h" -class FSR3Upscaler_Vulkan : FSR3Upscaler_FFXBase +class FSR3Upscaler_Vulkan : public FSR3Upscaler_FFXBase { public: - FSR3Upscaler_Vulkan(IUnityInterfaces* unityInterfaces, IUnityGraphicsVulkan* graphicsDevice) : - FSR3Upscaler_FFXBase(unityInterfaces), + FSR3Upscaler_Vulkan(IUnityLog* log, IUnityGraphicsVulkan* graphicsDevice) : + FSR3Upscaler_FFXBase(log), m_GraphicsDevice(graphicsDevice), m_VulkanBackendDesc() { } @@ -19,7 +20,7 @@ public: protected: bool InitFeature(FSR3Feature_FFX& feature, const FSR3CommandInitializationData* initData) override; - void SetTexture(FSR3Texture textureType, UnityTextureID textureID, const UnityRenderingExtTextureUpdateParamsV2* params, FSR3TextureDesc* outTextureDesc) override; + void SetTexture(FSR3Texture textureType, UnityTextureID textureID, uint32_t width, uint32_t height, FSR3TextureDesc* outTextureDesc) override; void Execute(FSR3Feature_FFX& feature, const FSR3CommandExecutionData* execData) override; void AwaitEndOfFrame(uint64_t frameValue) override; diff --git a/Upscaler.h b/Upscaler.h new file mode 100644 index 0000000..6966b46 --- /dev/null +++ b/Upscaler.h @@ -0,0 +1,22 @@ +#pragma once +#include + +#include "UnityPluginAPI/IUnityInterface.h" +#include "FSR3UnityTypes.h" + +class Upscaler +{ +public: + virtual bool Init() = 0; // Called by AMDUP_InitAPI, does FidelityFX library loading + virtual void Shutdown() = 0; + + virtual uint32_t CreateFeatureSlot() = 0; + virtual bool InitFeature(const FSR3CommandInitializationData* initData) = 0; + virtual void DestroyFeature(uint32_t featureSlot) = 0; + + virtual void ClearTextureTable(uint32_t featureSlot) = 0; + virtual void SetTextureSlot(uint32_t featureSlot, uint32_t textureSlot, UnityTextureID textureID, uint32_t width, uint32_t height) = 0; + + virtual void Execute(const FSR3CommandExecutionData* execData) = 0; + virtual void PostExecute(const FSR3CommandExecutionData* execData) = 0; +}; diff --git a/UpscalerGraphicsDevice.h b/UpscalerGraphicsDevice.h index b15a08d..07f3c65 100644 --- a/UpscalerGraphicsDevice.h +++ b/UpscalerGraphicsDevice.h @@ -1,21 +1,14 @@ #pragma once -#include +#include "Upscaler.h" #include #include #include -#include "UnityPluginAPI/IUnityInterface.h" -#include "UnityPluginAPI/IUnityRenderingExtensions.h" - -#include "FSR3UnityTypes.h" - -template class UpscalerGraphicsDevice +template class UpscalerGraphicsDevice: public Upscaler { public: - virtual bool Init() = 0; // Called by AMDUP_InitAPI, does FidelityFX library loading - - void Shutdown() + void Shutdown() override { // Called by AMDUP_ShutdownAPI, destroys all features, cleans up internal resources size_t numFeatures = 0; @@ -34,13 +27,13 @@ public: DoShutdown(); } - uint32_t CreateFeatureSlot() + uint32_t CreateFeatureSlot() override { std::lock_guard lock(m_Mutex); return AllocateFeatureSlot(); } - virtual bool InitFeature(const FSR3CommandInitializationData* initData) + bool InitFeature(const FSR3CommandInitializationData* initData) override { std::lock_guard lock(m_Mutex); @@ -52,7 +45,7 @@ public: return InitFeature(feature, initData); } - void DestroyFeature(uint32_t featureSlot) + void DestroyFeature(uint32_t featureSlot) override { // Called by FSR3PluginEvent::eDestroyFeature event and Shutdown uint64_t dispatchFrameValue = 0; @@ -80,7 +73,7 @@ public: FreeFeatureSlot(featureSlot); } - virtual void ClearTextureTable(uint32_t featureSlot) + void ClearTextureTable(uint32_t featureSlot) override { if (featureSlot < 0 || featureSlot >= m_Features.size()) return; @@ -88,7 +81,7 @@ public: memset(&m_Features[featureSlot].textureTable, 0, sizeof(FSR3TextureTable)); } - virtual void SetTextureSlot(uint32_t featureSlot, uint32_t textureSlot, UnityTextureID textureID, const UnityRenderingExtTextureUpdateParamsV2* params) + void SetTextureSlot(uint32_t featureSlot, uint32_t textureSlot, UnityTextureID textureID, uint32_t width, uint32_t height) override { if (featureSlot < 0 || featureSlot >= m_Features.size()) return; @@ -96,10 +89,10 @@ 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((FSR3Texture)textureSlot, textureID, params, textureDesc); + SetTexture((FSR3Texture)textureSlot, textureID, width, height, textureDesc); } - virtual void Execute(const FSR3CommandExecutionData* execData) + void Execute(const FSR3CommandExecutionData* execData) override { std::lock_guard lock(m_Mutex); @@ -114,7 +107,7 @@ public: Execute(feature, execData); } - virtual void PostExecute(const FSR3CommandExecutionData* execData) + void PostExecute(const FSR3CommandExecutionData* execData) override { std::lock_guard lock(m_Mutex); @@ -133,7 +126,7 @@ protected: virtual bool IsValidFeature(TFeature& feature) = 0; virtual bool InitFeature(TFeature& feature, const FSR3CommandInitializationData* initData) = 0; - virtual void SetTexture(FSR3Texture textureType, UnityTextureID textureID, const UnityRenderingExtTextureUpdateParamsV2* params, FSR3TextureDesc* outTextureDesc) = 0; + virtual void SetTexture(FSR3Texture textureType, UnityTextureID textureID, uint32_t width, uint32_t height, FSR3TextureDesc* outTextureDesc) = 0; virtual void Execute(TFeature& feature, const FSR3CommandExecutionData* execData) = 0; virtual void PostExecute(TFeature& feature, const FSR3CommandExecutionData* execData) { }