#include #include #include #include #include "UnityPluginAPI/IUnityInterface.h" #include "UnityPluginAPI/IUnityLog.h" #include "UnityPluginAPI/IUnityGraphics.h" #include "UnityPluginAPI/IUnityRenderingExtensions.h" #include #include #include "UnityPluginAPI/IUnityGraphicsD3D12.h" #include "FSR3UnityTypes.h" static const int32_t BaseEventId = 0; static IUnityInterfaces* s_UnityInterfaces = nullptr; static IUnityLog* s_Log = nullptr; static IUnityGraphics* s_Graphics = nullptr; static IUnityGraphicsD3D12v7* s_GraphicsD3D12 = 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 FSR3Context { // TODO: contains FSR3 context object + related metadata (texture table etc) }; static std::vector s_Contexts; static std::queue s_FeatureSlots; static std::mutex s_FeatureMutex; // Unity plugin load event extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces) { s_UnityInterfaces = unityInterfaces; s_Log = unityInterfaces->Get(); s_Graphics = unityInterfaces->Get(); s_Graphics->RegisterDeviceEventCallback(OnGraphicsDeviceEvent); // Run OnGraphicsDeviceEvent(initialize) manually on plugin load // to not miss the event in case the graphics device is already initialized OnGraphicsDeviceEvent(kUnityGfxDeviceEventInitialize); } // Unity plugin unload event extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload() { s_Graphics->UnregisterDeviceEventCallback(OnGraphicsDeviceEvent); } static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType) { switch (eventType) { case kUnityGfxDeviceEventInitialize: { s_RendererType = s_Graphics->GetRenderer(); if (s_RendererType != kUnityGfxRendererD3D12) return; s_GraphicsD3D12 = s_UnityInterfaces->Get(); if (s_GraphicsD3D12 == nullptr) { UNITY_LOG_ERROR(s_Log, "Could not obtain D3D12 Graphics interface!"); return; } break; } case kUnityGfxDeviceEventShutdown: { s_GraphicsD3D12 = nullptr; s_RendererType = kUnityGfxRendererNull; break; } case kUnityGfxDeviceEventBeforeReset: { break; } case kUnityGfxDeviceEventAfterReset: { break; } }; } // Thread-safe allocation of FSR3 Context feature slot static uint32_t AllocateFeatureSlot() { std::lock_guard lock(s_FeatureMutex); if (s_FeatureSlots.empty()) { uint32_t featureSlot = (uint32_t)s_Contexts.size(); s_Contexts.push_back(std::move(FSR3Context())); return featureSlot; } uint32_t featureSlot = s_FeatureSlots.front(); s_FeatureSlots.pop(); return featureSlot; } // Thread-safe freeing and clearing of FSR3 Context feature slot static void FreeFeatureSlot(uint32_t featureSlot) { std::lock_guard lock(s_FeatureMutex); s_FeatureSlots.push(featureSlot); memset(&s_Contexts[featureSlot], 0, sizeof(FSR3Context)); } extern "C" bool UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_InitApi() { // TODO: implement return false; } extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_ShutdownApi() { // TODO: implement } extern "C" uint32_t UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_GetDeviceVersion() { return 0x0u; } extern "C" UnityRenderingEventAndData UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_GetRenderEventCallback() { return OnRenderEventAndData; } extern "C" UnityRenderingEventAndData UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_GetSetTextureEventCallback() { return OnSetTextureEvent; } extern "C" uint32_t UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_CreateFeatureSlot() { return AllocateFeatureSlot(); } extern "C" bool UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_GetRenderResolutionFromQualityMode(FSR3Quality qualityMode, uint32_t displayWidth, uint32_t displayHeight, uint32_t* renderWidth, uint32_t* renderHeight) { // TODO: implement return false; } extern "C" float UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_GetUpscaleRatioFromQualityMode(FSR3Quality qualityMode) { // TODO: implement return 1.0f; } extern "C" int32_t UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_GetBaseEventId() { return BaseEventId; } // Plugin function to handle a specific rendering event static void UNITY_INTERFACE_API OnRenderEventAndData(int eventID, void* data) { // User rendering code switch (eventID) { case BaseEventId + FSR3PluginEvent::eDestroyFeature: { uint32_t featureSlot = (uint32_t)(int64_t)data; // TODO: destroy FSR3Context at feature slot index FreeFeatureSlot(featureSlot); break; } case BaseEventId + FSR3PluginEvent::eExecute: { auto* params = (FSR3CommandExecutionData*)data; break; } case BaseEventId + FSR3PluginEvent::ePostExecute: { auto* params = (FSR3CommandExecutionData*)data; break; } case BaseEventId + FSR3PluginEvent::eInit: { auto* params = (FSR3CommandInitializationData*)data; break; } } } static void UNITY_INTERFACE_API OnSetTextureEvent(int eventID, void* data) { auto* params = (UnityRenderingExtTextureUpdateParamsV2*)data; uint32_t featureSlot = (params->userData >> 16) & 0xFFFF; uint32_t textureSlot = (params->userData >> 1) & 0x7FFF; // TODO: could just use as numeric index to calculate a pointer offset uint32_t clearTextureTable = params->userData & 0x1; // User rendering code switch (eventID) { case kUnityRenderingExtEventUpdateTextureBeginV2: { break; } case kUnityRenderingExtEventUpdateTextureEndV2: { break; } } }