Browse Source

Reworked core plugin code to make use of the upscaler classes, fixed some issues along the way

master
Nico de Poel 10 months ago
parent
commit
49d622a763
  1. 4
      FSR2Upscaler_DX11.cpp
  2. 7
      FSR2Upscaler_DX11.h
  3. 554
      FSR3UnityPlugin.cpp
  4. 1
      FSR3UnityPlugin.vcxproj
  5. 3
      FSR3UnityPlugin.vcxproj.filters
  6. 2
      FSR3Upscaler_DX12.cpp
  7. 9
      FSR3Upscaler_DX12.h
  8. 7
      FSR3Upscaler_FFXBase.h
  9. 6
      FSR3Upscaler_Vulkan.cpp
  10. 9
      FSR3Upscaler_Vulkan.h
  11. 22
      Upscaler.h
  12. 31
      UpscalerGraphicsDevice.h

4
FSR2Upscaler_DX11.cpp

@ -34,9 +34,9 @@ bool FSR2Upscaler_DX11::InitFeature(FSR2Feature& feature, const FSR3CommandIniti
return feature.isValid; 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) void FSR2Upscaler_DX11::Execute(FSR2Feature& feature, const FSR3CommandExecutionData* execData)

7
FSR2Upscaler_DX11.h

@ -4,6 +4,7 @@
#include "ffx-fsr2-api/ffx_fsr2.h" #include "ffx-fsr2-api/ffx_fsr2.h"
#include <d3d11.h> #include <d3d11.h>
#include "UnityPluginAPI/IUnityGraphics.h"
#include "UnityPluginAPI/IUnityGraphicsD3D11.h" #include "UnityPluginAPI/IUnityGraphicsD3D11.h"
struct FSR2Feature struct FSR2Feature
@ -20,10 +21,10 @@ struct FSR2Feature
FSR3TextureTable textureTable; FSR3TextureTable textureTable;
}; };
class FSR2Upscaler_DX11 : UpscalerGraphicsDevice<FSR2Feature>
class FSR2Upscaler_DX11 : public UpscalerGraphicsDevice<FSR2Feature>
{ {
public: public:
FSR2Upscaler_DX11(IUnityInterfaces* unityInterfaces, IUnityGraphicsD3D11* graphicsDevice) :
FSR2Upscaler_DX11(IUnityGraphicsD3D11* graphicsDevice) :
m_GraphicsDevice(graphicsDevice), m_DX11Device(nullptr), m_Fsr2Interface() m_GraphicsDevice(graphicsDevice), m_DX11Device(nullptr), m_Fsr2Interface()
{ {
} }
@ -34,7 +35,7 @@ protected:
bool IsValidFeature(FSR2Feature& feature); bool IsValidFeature(FSR2Feature& feature);
bool InitFeature(FSR2Feature& feature, const FSR3CommandInitializationData* initData); 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 Execute(FSR2Feature& feature, const FSR3CommandExecutionData* execData);
void AwaitEndOfFrame(uint64_t frameValue); void AwaitEndOfFrame(uint64_t frameValue);

554
FSR3UnityPlugin.cpp

@ -1,74 +1,26 @@
#include <stdint.h>
#include <sstream>
#include <vector>
#include <queue>
#include <mutex>
#include "Upscaler.h"
#include "UnityPluginAPI/IUnityInterface.h" #include "UnityPluginAPI/IUnityInterface.h"
#include "UnityPluginAPI/IUnityLog.h" #include "UnityPluginAPI/IUnityLog.h"
#include "UnityPluginAPI/IUnityGraphics.h" #include "UnityPluginAPI/IUnityGraphics.h"
#include "UnityPluginAPI/IUnityRenderingExtensions.h" #include "UnityPluginAPI/IUnityRenderingExtensions.h"
#include <d3d11.h>
#include <d3d12.h>
#include <dxgi.h>
#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 const int32_t BaseEventId = 313;
static IUnityInterfaces* s_UnityInterfaces = nullptr; static IUnityInterfaces* s_UnityInterfaces = nullptr;
static IUnityLog* s_Log = nullptr; static IUnityLog* s_Log = nullptr;
static IUnityGraphics* s_Graphics = 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 UnityGfxRenderer s_RendererType = kUnityGfxRendererNull;
static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType); static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType);
static void UNITY_INTERFACE_API OnRenderEventAndData(int eventID, void* data); static void UNITY_INTERFACE_API OnRenderEventAndData(int eventID, void* data);
static void UNITY_INTERFACE_API OnSetTextureEvent(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<FSR3Feature> s_Features;
static std::queue<uint32_t> 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 // 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)
@ -92,8 +44,6 @@ extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload()
static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType) static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType)
{ {
std::lock_guard<std::mutex> lock(s_FeatureMutex);
switch (eventType) switch (eventType)
{ {
case kUnityGfxDeviceEventInitialize: case kUnityGfxDeviceEventInitialize:
@ -103,44 +53,50 @@ static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType ev
{ {
case kUnityGfxRendererD3D11: case kUnityGfxRendererD3D11:
{ {
s_GraphicsD3D11 = s_UnityInterfaces->Get<IUnityGraphicsD3D11>();
if (s_GraphicsD3D11 == nullptr)
auto* graphicsD3D11 = s_UnityInterfaces->Get<IUnityGraphicsD3D11>();
if (graphicsD3D11 == nullptr)
{ {
UNITY_LOG_ERROR(s_Log, "Could not obtain D3D11 Graphics interface!"); UNITY_LOG_ERROR(s_Log, "Could not obtain D3D11 Graphics interface!");
return; return;
} }
s_Upscaler = new FSR2Upscaler_DX11(graphicsD3D11);
break; break;
} }
case kUnityGfxRendererD3D12: case kUnityGfxRendererD3D12:
{ {
s_GraphicsD3D12 = s_UnityInterfaces->Get<IUnityGraphicsD3D12v7>();
if (s_GraphicsD3D12 == nullptr)
auto* graphicsD3D12 = s_UnityInterfaces->Get<IUnityGraphicsD3D12v7>();
if (graphicsD3D12 == nullptr)
{ {
UNITY_LOG_ERROR(s_Log, "Could not obtain D3D12 Graphics interface!"); UNITY_LOG_ERROR(s_Log, "Could not obtain D3D12 Graphics interface!");
return; return;
} }
s_Upscaler = new FSR3Upscaler_DX12(s_Log, graphicsD3D12);
UnityD3D12PluginEventConfig eventConfig; UnityD3D12PluginEventConfig eventConfig;
eventConfig.graphicsQueueAccess = kUnityD3D12GraphicsQueueAccess_DontCare; eventConfig.graphicsQueueAccess = kUnityD3D12GraphicsQueueAccess_DontCare;
eventConfig.flags = kUnityD3D12EventConfigFlag_EnsurePreviousFrameSubmission | kUnityD3D12EventConfigFlag_FlushCommandBuffers | kUnityD3D12EventConfigFlag_SyncWorkerThreads | kUnityD3D12EventConfigFlag_ModifiesCommandBuffersState; eventConfig.flags = kUnityD3D12EventConfigFlag_EnsurePreviousFrameSubmission | kUnityD3D12EventConfigFlag_FlushCommandBuffers | kUnityD3D12EventConfigFlag_SyncWorkerThreads | kUnityD3D12EventConfigFlag_ModifiesCommandBuffersState;
eventConfig.ensureActiveRenderTextureIsBound = false; eventConfig.ensureActiveRenderTextureIsBound = false;
s_GraphicsD3D12->ConfigureEvent(BaseEventId + FSR3PluginEvent::eExecute, &eventConfig);
graphicsD3D12->ConfigureEvent(BaseEventId + FSR3PluginEvent::eExecute, &eventConfig);
break; break;
} }
case kUnityGfxRendererVulkan: case kUnityGfxRendererVulkan:
{ {
s_GraphicsVulkan = s_UnityInterfaces->Get<IUnityGraphicsVulkan>();
if (s_GraphicsVulkan == nullptr)
auto* graphicsVulkan = s_UnityInterfaces->Get<IUnityGraphicsVulkan>();
if (graphicsVulkan == nullptr)
{ {
UNITY_LOG_ERROR(s_Log, "Could not obtain Vulkan Graphics interface!"); UNITY_LOG_ERROR(s_Log, "Could not obtain Vulkan Graphics interface!");
return; return;
} }
s_Upscaler = new FSR3Upscaler_Vulkan(s_Log, graphicsVulkan);
UnityVulkanPluginEventConfig eventConfig; UnityVulkanPluginEventConfig eventConfig;
eventConfig.graphicsQueueAccess = kUnityVulkanGraphicsQueueAccess_DontCare; eventConfig.graphicsQueueAccess = kUnityVulkanGraphicsQueueAccess_DontCare;
eventConfig.flags = kUnityVulkanEventConfigFlag_EnsurePreviousFrameSubmission | kUnityVulkanEventConfigFlag_FlushCommandBuffers | kUnityVulkanEventConfigFlag_SyncWorkerThreads | kUnityVulkanEventConfigFlag_ModifiesCommandBuffersState; eventConfig.flags = kUnityVulkanEventConfigFlag_EnsurePreviousFrameSubmission | kUnityVulkanEventConfigFlag_FlushCommandBuffers | kUnityVulkanEventConfigFlag_SyncWorkerThreads | kUnityVulkanEventConfigFlag_ModifiesCommandBuffersState;
eventConfig.renderPassPrecondition = kUnityVulkanRenderPass_EnsureInside; eventConfig.renderPassPrecondition = kUnityVulkanRenderPass_EnsureInside;
s_GraphicsVulkan->ConfigureEvent(BaseEventId + FSR3PluginEvent::eExecute, &eventConfig);
graphicsVulkan->ConfigureEvent(BaseEventId + FSR3PluginEvent::eExecute, &eventConfig);
break; break;
} }
} }
@ -149,9 +105,12 @@ static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType ev
} }
case kUnityGfxDeviceEventShutdown: case kUnityGfxDeviceEventShutdown:
{ {
s_GraphicsVulkan = nullptr;
s_GraphicsD3D12 = nullptr;
s_GraphicsD3D11 = nullptr;
if (s_Upscaler != nullptr)
{
delete s_Upscaler;
s_Upscaler = nullptr;
}
s_RendererType = kUnityGfxRendererNull; s_RendererType = kUnityGfxRendererNull;
break; 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<const char*> versionNames;
std::vector<uint64_t> 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() extern "C" bool UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_InitApi()
{ {
std::lock_guard<std::mutex> 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; 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<std::mutex> 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<std::mutex> 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() extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_ShutdownApi()
{ {
size_t numFeatures = 0;
if (s_Upscaler != nullptr)
{ {
std::lock_guard<std::mutex> lock(s_FeatureMutex);
numFeatures = s_Features.size();
s_Upscaler->Shutdown();
} }
for (uint32_t slot = 0; slot < numFeatures; ++slot)
{
DestroyFeature(slot);
}
std::lock_guard<std::mutex> lock(s_FeatureMutex);
if (s_ffxModule != nullptr)
{
FreeLibrary(s_ffxModule);
s_ffxModule = nullptr;
}
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() 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() extern "C" uint32_t UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_CreateFeatureSlot()
{ {
std::lock_guard<std::mutex> 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) 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; 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 // Plugin function to handle a specific rendering event
static void UNITY_INTERFACE_API OnRenderEventAndData(int eventID, void* data) 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; return;
// User rendering code // User rendering code
@ -468,193 +212,26 @@ static void UNITY_INTERFACE_API OnRenderEventAndData(int eventID, void* data)
{ {
case BaseEventId + FSR3PluginEvent::eDestroyFeature: 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; break;
} }
case BaseEventId + FSR3PluginEvent::eExecute: case BaseEventId + FSR3PluginEvent::eExecute:
{ {
std::lock_guard<std::mutex> 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; break;
} }
case BaseEventId + FSR3PluginEvent::ePostExecute: case BaseEventId + FSR3PluginEvent::ePostExecute:
{ {
auto* params = (FSR3CommandExecutionData*)data;
auto* execData = (FSR3CommandExecutionData*)data;
s_Upscaler->PostExecute(execData);
break; break;
} }
case BaseEventId + FSR3PluginEvent::eInit: case BaseEventId + FSR3PluginEvent::eInit:
{ {
std::lock_guard<std::mutex> 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; 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) static void UNITY_INTERFACE_API OnSetTextureEvent(int eventID, void* data)
{ {
std::lock_guard<std::mutex> lock(s_FeatureMutex);
if (s_Upscaler == nullptr)
return;
auto* params = (UnityRenderingExtTextureUpdateParamsV2*)data; 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 textureSlot = (params->userData >> 1) & 0x7FFF;
uint32_t clearTextureTable = params->userData & 0x1; uint32_t clearTextureTable = params->userData & 0x1;
if (featureSlot < 0 || featureSlot >= s_Features.size())
return;
auto& feature = s_Features[featureSlot];
// User rendering code // User rendering code
switch (eventID) switch (eventID)
{ {
@ -683,44 +256,13 @@ static void UNITY_INTERFACE_API OnSetTextureEvent(int eventID, void* data)
{ {
if (clearTextureTable) if (clearTextureTable)
{ {
memset(&feature.textureTable, 0, sizeof(FSR3TextureTable));
s_Upscaler->ClearTextureTable(featureSlot);
} }
break; break;
} }
case kUnityRenderingExtEventUpdateTextureEndV2: 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; break;
} }
} }

1
FSR3UnityPlugin.vcxproj

@ -162,6 +162,7 @@
<ClInclude Include="FSR3Upscaler_DX12.h" /> <ClInclude Include="FSR3Upscaler_DX12.h" />
<ClInclude Include="FSR3Upscaler_FFXBase.h" /> <ClInclude Include="FSR3Upscaler_FFXBase.h" />
<ClInclude Include="FSR3Upscaler_Vulkan.h" /> <ClInclude Include="FSR3Upscaler_Vulkan.h" />
<ClInclude Include="Upscaler.h" />
<ClInclude Include="UpscalerGraphicsDevice.h" /> <ClInclude Include="UpscalerGraphicsDevice.h" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

3
FSR3UnityPlugin.vcxproj.filters

@ -47,5 +47,8 @@
<ClInclude Include="FSR2Upscaler_DX11.h"> <ClInclude Include="FSR2Upscaler_DX11.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Upscaler.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>

2
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); 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); outTextureDesc->image = (intptr_t)m_GraphicsDevice->TextureFromNativeTexture(textureID);
} }

9
FSR3Upscaler_DX12.h

@ -4,13 +4,14 @@
#include "ffx_api/ffx_upscale.hpp" #include "ffx_api/ffx_upscale.hpp"
#include "ffx_api/dx12/ffx_api_dx12.hpp" #include "ffx_api/dx12/ffx_api_dx12.hpp"
#include "UnityPluginAPI/IUnityGraphics.h"
#include "UnityPluginAPI/IUnityGraphicsD3D12.h" #include "UnityPluginAPI/IUnityGraphicsD3D12.h"
class FSR3Upscaler_DX12 : FSR3Upscaler_FFXBase
class FSR3Upscaler_DX12 : public FSR3Upscaler_FFXBase
{ {
public: 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) m_GraphicsDevice(graphicsDevice), m_DX12BackendDesc(), m_FrameFenceEventHandle(nullptr)
{ {
} }
@ -19,7 +20,7 @@ public:
protected: protected:
bool InitFeature(FSR3Feature_FFX& feature, const FSR3CommandInitializationData* initData) override; 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 Execute(FSR3Feature_FFX& feature, const FSR3CommandExecutionData* execData) override;
void AwaitEndOfFrame(uint64_t frameValue) override; void AwaitEndOfFrame(uint64_t frameValue) override;

7
FSR3Upscaler_FFXBase.h

@ -21,13 +21,12 @@ struct FSR3Feature_FFX
FSR3TextureTable textureTable; FSR3TextureTable textureTable;
}; };
class FSR3Upscaler_FFXBase : UpscalerGraphicsDevice<FSR3Feature_FFX>
class FSR3Upscaler_FFXBase : public UpscalerGraphicsDevice<FSR3Feature_FFX>
{ {
public: public:
FSR3Upscaler_FFXBase(IUnityInterfaces* unityInterfaces)
: m_ffxModule(NULL)
FSR3Upscaler_FFXBase(IUnityLog* log)
: m_Log(log), m_ffxModule(NULL)
{ {
m_Log = unityInterfaces->Get<IUnityLog>();
} }
protected: protected:

6
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); 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; 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)) kUnityVulkanResourceAccess_PipelineBarrier, &image))
{ {
outTextureDesc->image = (intptr_t)image.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; outTextureDesc->format = (uint32_t)image.format;
} }
else else

9
FSR3Upscaler_Vulkan.h

@ -4,13 +4,14 @@
#include "ffx_api/ffx_upscale.hpp" #include "ffx_api/ffx_upscale.hpp"
#include "ffx_api/vk/ffx_api_vk.hpp" #include "ffx_api/vk/ffx_api_vk.hpp"
#include "UnityPluginAPI/IUnityGraphics.h"
#include "UnityPluginAPI/IUnityGraphicsVulkan.h" #include "UnityPluginAPI/IUnityGraphicsVulkan.h"
class FSR3Upscaler_Vulkan : FSR3Upscaler_FFXBase
class FSR3Upscaler_Vulkan : public FSR3Upscaler_FFXBase
{ {
public: public:
FSR3Upscaler_Vulkan(IUnityInterfaces* unityInterfaces, IUnityGraphicsVulkan* graphicsDevice) :
FSR3Upscaler_FFXBase(unityInterfaces),
FSR3Upscaler_Vulkan(IUnityLog* log, IUnityGraphicsVulkan* graphicsDevice) :
FSR3Upscaler_FFXBase(log),
m_GraphicsDevice(graphicsDevice), m_VulkanBackendDesc() m_GraphicsDevice(graphicsDevice), m_VulkanBackendDesc()
{ {
} }
@ -19,7 +20,7 @@ public:
protected: protected:
bool InitFeature(FSR3Feature_FFX& feature, const FSR3CommandInitializationData* initData) override; 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 Execute(FSR3Feature_FFX& feature, const FSR3CommandExecutionData* execData) override;
void AwaitEndOfFrame(uint64_t frameValue) override; void AwaitEndOfFrame(uint64_t frameValue) override;

22
Upscaler.h

@ -0,0 +1,22 @@
#pragma once
#include <stdint.h>
#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;
};

31
UpscalerGraphicsDevice.h

@ -1,21 +1,14 @@
#pragma once #pragma once
#include <stdint.h>
#include "Upscaler.h"
#include <vector> #include <vector>
#include <queue> #include <queue>
#include <mutex> #include <mutex>
#include "UnityPluginAPI/IUnityInterface.h"
#include "UnityPluginAPI/IUnityRenderingExtensions.h"
#include "FSR3UnityTypes.h"
template<typename TFeature> class UpscalerGraphicsDevice
template<typename TFeature> class UpscalerGraphicsDevice: public Upscaler
{ {
public: 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 // Called by AMDUP_ShutdownAPI, destroys all features, cleans up internal resources
size_t numFeatures = 0; size_t numFeatures = 0;
@ -34,13 +27,13 @@ public:
DoShutdown(); DoShutdown();
} }
uint32_t CreateFeatureSlot()
uint32_t CreateFeatureSlot() override
{ {
std::lock_guard<std::mutex> lock(m_Mutex); std::lock_guard<std::mutex> lock(m_Mutex);
return AllocateFeatureSlot(); return AllocateFeatureSlot();
} }
virtual bool InitFeature(const FSR3CommandInitializationData* initData)
bool InitFeature(const FSR3CommandInitializationData* initData) override
{ {
std::lock_guard<std::mutex> lock(m_Mutex); std::lock_guard<std::mutex> lock(m_Mutex);
@ -52,7 +45,7 @@ public:
return InitFeature(feature, initData); return InitFeature(feature, initData);
} }
void DestroyFeature(uint32_t featureSlot)
void DestroyFeature(uint32_t featureSlot) override
{ {
// Called by FSR3PluginEvent::eDestroyFeature event and Shutdown // Called by FSR3PluginEvent::eDestroyFeature event and Shutdown
uint64_t dispatchFrameValue = 0; uint64_t dispatchFrameValue = 0;
@ -80,7 +73,7 @@ public:
FreeFeatureSlot(featureSlot); FreeFeatureSlot(featureSlot);
} }
virtual void ClearTextureTable(uint32_t featureSlot)
void ClearTextureTable(uint32_t featureSlot) override
{ {
if (featureSlot < 0 || featureSlot >= m_Features.size()) if (featureSlot < 0 || featureSlot >= m_Features.size())
return; return;
@ -88,7 +81,7 @@ public:
memset(&m_Features[featureSlot].textureTable, 0, sizeof(FSR3TextureTable)); 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()) if (featureSlot < 0 || featureSlot >= m_Features.size())
return; return;
@ -96,10 +89,10 @@ public:
// We organized the texture table struct to be ordered the same as the texture slot enum // 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 // 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; 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<std::mutex> lock(m_Mutex); std::lock_guard<std::mutex> lock(m_Mutex);
@ -114,7 +107,7 @@ public:
Execute(feature, execData); Execute(feature, execData);
} }
virtual void PostExecute(const FSR3CommandExecutionData* execData)
void PostExecute(const FSR3CommandExecutionData* execData) override
{ {
std::lock_guard<std::mutex> lock(m_Mutex); std::lock_guard<std::mutex> lock(m_Mutex);
@ -133,7 +126,7 @@ protected:
virtual bool IsValidFeature(TFeature& feature) = 0; virtual bool IsValidFeature(TFeature& feature) = 0;
virtual bool InitFeature(TFeature& feature, const FSR3CommandInitializationData* initData) = 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 Execute(TFeature& feature, const FSR3CommandExecutionData* execData) = 0;
virtual void PostExecute(TFeature& feature, const FSR3CommandExecutionData* execData) { } virtual void PostExecute(TFeature& feature, const FSR3CommandExecutionData* execData) { }

Loading…
Cancel
Save