Browse Source

Added lock guards to all exported functions that interact with the features or the graphics contexts, as well as additional validity checks. Protects against most of Unity's weird unsafe behavior when using the plugin, fixing the majority of crashes.

master
Nico de Poel 11 months ago
parent
commit
aa40402c28
  1. 51
      FSR3UnityPlugin.cpp

51
FSR3UnityPlugin.cpp

@ -87,6 +87,8 @@ 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:
@ -147,11 +149,8 @@ static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType ev
}; };
} }
// Thread-safe allocation of feature slot
static uint32_t AllocateFeatureSlot() static uint32_t AllocateFeatureSlot()
{ {
std::lock_guard<std::mutex> lock(s_FeatureMutex);
if (s_FeatureSlots.empty()) if (s_FeatureSlots.empty())
{ {
// Create a new feature if there are no free slots // Create a new feature if there are no free slots
@ -167,11 +166,8 @@ static uint32_t AllocateFeatureSlot()
return featureSlot; return featureSlot;
} }
// Thread-safe freeing and clearing of feature slot
static void FreeFeatureSlot(uint32_t featureSlot) static void FreeFeatureSlot(uint32_t featureSlot)
{ {
std::lock_guard<std::mutex> lock(s_FeatureMutex);
s_FeatureSlots.push(featureSlot); s_FeatureSlots.push(featureSlot);
memset(&s_Features[featureSlot], 0, sizeof(FSR3Feature)); memset(&s_Features[featureSlot], 0, sizeof(FSR3Feature));
} }
@ -203,6 +199,8 @@ static bool LoadFidelityFXLibrary(_In_ LPCWSTR lpLibFileName)
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) if (s_GraphicsD3D11 != nullptr)
{ {
ID3D11Device* device = s_GraphicsD3D11->GetDevice(); ID3D11Device* device = s_GraphicsD3D11->GetDevice();
@ -242,23 +240,30 @@ extern "C" bool UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_InitApi()
return false; return false;
} }
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_ShutdownApi()
{
for (uint32_t slot = 0; slot < s_Features.size(); ++slot)
static void DestroyFeature(uint32_t featureSlot)
{ {
auto& feature = s_Features[slot];
auto& feature = s_Features[featureSlot];
if (feature.upscalingContext != nullptr) if (feature.upscalingContext != nullptr)
{ {
s_ffxFunctions.DestroyContext(&feature.upscalingContext, nullptr); s_ffxFunctions.DestroyContext(&feature.upscalingContext, nullptr);
FreeFeatureSlot(slot);
FreeFeatureSlot(featureSlot);
} }
else if (feature.isValid) else if (feature.isValid)
{ {
ffxFsr2ContextDestroy(&feature.fsr2Context); ffxFsr2ContextDestroy(&feature.fsr2Context);
FreeFeatureSlot(slot);
FreeFeatureSlot(featureSlot);
} }
} }
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_ShutdownApi()
{
std::lock_guard<std::mutex> lock(s_FeatureMutex);
for (uint32_t slot = 0; slot < s_Features.size(); ++slot)
{
DestroyFeature(slot);
}
if (s_ffxModule != nullptr) if (s_ffxModule != nullptr)
{ {
FreeLibrary(s_ffxModule); FreeLibrary(s_ffxModule);
@ -297,6 +302,7 @@ 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(); return AllocateFeatureSlot();
} }
@ -355,6 +361,11 @@ static FfxApiResource GetVulkanTextureResource(UnityVulkanInstance& instance, FS
// 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)
{ {
std::lock_guard<std::mutex> lock(s_FeatureMutex);
if (s_DX11Device == nullptr && s_DX12BackendDesc.device == nullptr && s_VulkanBackendDesc.vkDevice == nullptr)
return;
// User rendering code // User rendering code
switch (eventID) switch (eventID)
{ {
@ -364,17 +375,7 @@ static void UNITY_INTERFACE_API OnRenderEventAndData(int eventID, void* data)
if (featureSlot < 0 || featureSlot >= s_Features.size()) if (featureSlot < 0 || featureSlot >= s_Features.size())
return; return;
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);
}
DestroyFeature(featureSlot);
break; break;
} }
case BaseEventId + FSR3PluginEvent::eExecute: case BaseEventId + FSR3PluginEvent::eExecute:
@ -384,6 +385,8 @@ static void UNITY_INTERFACE_API OnRenderEventAndData(int eventID, void* data)
return; return;
auto& feature = s_Features[params->featureSlot]; auto& feature = s_Features[params->featureSlot];
if (feature.upscalingContext == nullptr && !feature.isValid)
return;
if (s_GraphicsD3D11 != nullptr) if (s_GraphicsD3D11 != nullptr)
{ {
@ -543,6 +546,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);
auto* params = (UnityRenderingExtTextureUpdateParamsV2*)data; auto* params = (UnityRenderingExtTextureUpdateParamsV2*)data;
// userData = (featureId & (int) ushort.MaxValue) << 16 | (textureSlot & (int) short.MaxValue) << 1 | (clearTextureTable ? 1 : 0); // userData = (featureId & (int) ushort.MaxValue) << 16 | (textureSlot & (int) short.MaxValue) << 1 | (clearTextureTable ? 1 : 0);

Loading…
Cancel
Save