diff --git a/OptiScaler/OwnedMutex.h b/OptiScaler/OwnedMutex.h index fc35c303..12abaa29 100644 --- a/OptiScaler/OwnedMutex.h +++ b/OptiScaler/OwnedMutex.h @@ -8,7 +8,10 @@ class OwnedMutex { private: + // shared* as basic mutex must only be unlocked by thread that locked it std::shared_mutex mtx; + + // Written under mutex, read independently std::atomic owner {}; // don't use 0 public: @@ -33,6 +36,7 @@ class OwnedMutex mtx.unlock(); } + // Result is truthful only if and while locked uint32_t getOwner() { return owner.load(std::memory_order_seq_cst); } }; @@ -48,5 +52,7 @@ class OwnedLockGuard _mutex.lock(_owner_id); } + OwnedLockGuard(const OwnedLockGuard&) = delete; + ~OwnedLockGuard() { _mutex.unlockThis(_owner_id); } }; diff --git a/OptiScaler/framegen/ffx/FSRFG_Dx12.cpp b/OptiScaler/framegen/ffx/FSRFG_Dx12.cpp index 674004ef..7e76bf66 100644 --- a/OptiScaler/framegen/ffx/FSRFG_Dx12.cpp +++ b/OptiScaler/framegen/ffx/FSRFG_Dx12.cpp @@ -5,6 +5,7 @@ #include #include #include +#include // #define USE_QUEUE_FOR_FG @@ -100,10 +101,11 @@ bool FSRFG_Dx12::Dispatch(ID3D12GraphicsCommandList* cmdList, ID3D12Resource* ou auto frameIndex = _frameCount % BUFFER_COUNT; + std::optional lock; if (Config::Instance()->FGUseMutexForSwapchain.value_or_default()) { LOG_TRACE("Waiting Mutex 1, current: {}", Mutex.getOwner()); - Mutex.lock(1); + lock.emplace(Mutex, 1); LOG_TRACE("Accuired Mutex: {}", Mutex.getOwner()); } @@ -250,10 +252,9 @@ bool FSRFG_Dx12::Dispatch(ID3D12GraphicsCommandList* cmdList, ID3D12Resource* ou } } - if (Config::Instance()->FGUseMutexForSwapchain.value_or_default()) + if (lock) { LOG_TRACE("Releasing Mutex: {}", Mutex.getOwner()); - Mutex.unlockThis(1); } return retCode == FFX_API_RETURN_OK; @@ -522,10 +523,11 @@ void FSRFG_Dx12::FgDone() { return; + std::optional lock; if (Config::Instance()->FGUseMutexForSwapchain.value_or_default()) { LOG_TRACE("Waiting Mutex 1, current: {}", Mutex.getOwner()); - Mutex.lock(1); + lock.emplace(Mutex, 1); LOG_TRACE("Accuired Mutex: {}", Mutex.getOwner()); } @@ -545,10 +547,9 @@ void FSRFG_Dx12::FgDone() LOG_INFO("D3D12_Configure result: {0:X}", result); } - if (Config::Instance()->FGUseMutexForSwapchain.value_or_default()) + if (lock) { LOG_TRACE("Releasing Mutex: {}", Mutex.getOwner()); - Mutex.unlockThis(1); } } @@ -570,12 +571,11 @@ void FSRFG_Dx12::StopAndDestroyContext(bool destroy, bool shutDown, bool useMute LOG_DEBUG(""); - bool mutexTaken = false; + std::optional lock; if (Config::Instance()->FGUseMutexForSwapchain.value_or_default() && useMutex) { LOG_TRACE("Waiting Mutex 1, current: {}", Mutex.getOwner()); - Mutex.lock(1); - mutexTaken = true; + lock.emplace(Mutex, 1); LOG_TRACE("Accuired Mutex: {}", Mutex.getOwner()); } @@ -610,10 +610,9 @@ void FSRFG_Dx12::StopAndDestroyContext(bool destroy, bool shutDown, bool useMute if (shutDown || State::Instance().isShuttingDown) ReleaseObjects(); - if (mutexTaken) + if (lock) { LOG_TRACE("Releasing Mutex: {}", Mutex.getOwner()); - Mutex.unlockThis(1); } } @@ -703,10 +702,11 @@ bool FSRFG_Dx12::ReleaseSwapchain(HWND hwnd) LOG_DEBUG(""); + std::optional lock; if (Config::Instance()->FGUseMutexForSwapchain.value_or_default()) { LOG_TRACE("Waiting Mutex 1, current: {}", Mutex.getOwner()); - Mutex.lock(1); + lock.emplace(Mutex, 1); LOG_TRACE("Accuired Mutex: {}", Mutex.getOwner()); } @@ -723,10 +723,9 @@ bool FSRFG_Dx12::ReleaseSwapchain(HWND hwnd) _swapChainContext = nullptr; } - if (Config::Instance()->FGUseMutexForSwapchain.value_or_default()) + if (lock) { LOG_TRACE("Releasing Mutex: {}", Mutex.getOwner()); - Mutex.unlockThis(1); } return true; diff --git a/OptiScaler/hooks/HooksDx.cpp b/OptiScaler/hooks/HooksDx.cpp index 68de532c..438f382f 100644 --- a/OptiScaler/hooks/HooksDx.cpp +++ b/OptiScaler/hooks/HooksDx.cpp @@ -242,10 +242,9 @@ static HRESULT hkFGPresent(void* This, UINT SyncInterval, UINT Flags) // filter out posibly wrong measured high values if (elapsedTimeMs < 100.0) { - State::Instance().frameTimeMutex.lock(); + std::lock_guard lock(State::Instance().frameTimeMutex); State::Instance().upscaleTimes.push_back(elapsedTimeMs); State::Instance().upscaleTimes.pop_front(); - State::Instance().frameTimeMutex.unlock(); } } else @@ -425,10 +424,9 @@ static HRESULT Present(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags // filter out posibly wrong measured high values if (elapsedTimeMs < 100.0) { - State::Instance().frameTimeMutex.lock(); + std::lock_guard lock(State::Instance().frameTimeMutex); State::Instance().upscaleTimes.push_back(elapsedTimeMs); State::Instance().upscaleTimes.pop_front(); - State::Instance().frameTimeMutex.unlock(); } } else @@ -466,10 +464,9 @@ static HRESULT Present(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags // filter out posibly wrong measured high values if (elapsedTimeMs < 100.0) { - State::Instance().frameTimeMutex.lock(); + std::lock_guard lock(State::Instance().frameTimeMutex); State::Instance().upscaleTimes.push_back(elapsedTimeMs); State::Instance().upscaleTimes.pop_front(); - State::Instance().frameTimeMutex.unlock(); } } } diff --git a/OptiScaler/hooks/wrapped_swapchain.cpp b/OptiScaler/hooks/wrapped_swapchain.cpp index 83c0a1fd..b144101f 100644 --- a/OptiScaler/hooks/wrapped_swapchain.cpp +++ b/OptiScaler/hooks/wrapped_swapchain.cpp @@ -5,6 +5,7 @@ #include "HooksDx.h" #include +#include // Used RenderDoc's wrapped object as referance // https://github.com/baldurk/renderdoc/blob/v1.x/renderdoc/driver/dxgi/dxgi_wrapped.cpp @@ -228,14 +229,13 @@ HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::SetFullscreenState(BOOL Fullsc LOG_DEBUG("Fullscreen: {}, pTarget: {:X}", Fullscreen, (size_t) pTarget); HRESULT result = S_OK; - bool ffxLock = false; - + std::optional lock; { #ifdef USE_LOCAL_MUTEX // dlssg calls this from present it seems // don't try to get a mutex when present owns it while dlssg mod is enabled if (!(_localMutex.getOwner() == 4 && Config::Instance()->FGType.value_or_default() == FGType::Nukems)) - OwnedLockGuard lock(_localMutex, 3); + OwnedLockGuard(_localMutex, 3); #endif if (Config::Instance()->FGUseMutexForSwapchain.value_or_default()) { @@ -243,8 +243,7 @@ HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::SetFullscreenState(BOOL Fullsc if (State::Instance().currentFG != nullptr && State::Instance().currentFG->Mutex.getOwner() != 3) { LOG_TRACE("Waiting ffxMutex 3, current: {}", State::Instance().currentFG->Mutex.getOwner()); - State::Instance().currentFG->Mutex.lock(3); - ffxLock = true; + lock.emplace(State::Instance().currentFG->Mutex, 3); LOG_TRACE("Accuired ffxMutex: {}", State::Instance().currentFG->Mutex.getOwner()); } else @@ -299,10 +298,9 @@ HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::SetFullscreenState(BOOL Fullsc */ } - if (Config::Instance()->FGUseMutexForSwapchain.value_or_default() && ffxLock) + if (lock) { LOG_TRACE("Releasing ffxMutex: {}", State::Instance().currentFG->Mutex.getOwner()); - State::Instance().currentFG->Mutex.unlockThis(3); } return result; @@ -327,13 +325,14 @@ HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::ResizeBuffers(UINT BufferCount // dlssg calls this from present it seems // don't try to get a mutex when present owns it while dlssg mod is enabled if (!(_localMutex.getOwner() == 4 && Config::Instance()->FGType.value_or_default() == FGType::Nukems)) - OwnedLockGuard lock(_localMutex, 1); + OwnedLockGuard(_localMutex, 1); #endif + std::optional lock; if (State::Instance().currentFG != nullptr && Config::Instance()->FGUseMutexForSwapchain.value_or_default()) { LOG_TRACE("Waiting ffxMutex 3, current: {}", State::Instance().currentFG->Mutex.getOwner()); - State::Instance().currentFG->Mutex.lock(3); + lock.emplace(State::Instance().currentFG->Mutex, 3); LOG_TRACE("Accuired ffxMutex: {}", State::Instance().currentFG->Mutex.getOwner()); } @@ -436,10 +435,9 @@ HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::ResizeBuffers(UINT BufferCount LOG_DEBUG("result: {0:X}", (UINT) result); - if (State::Instance().currentFG != nullptr && Config::Instance()->FGUseMutexForSwapchain.value_or_default()) + if (lock) { LOG_TRACE("Releasing ffxMutex: {}", State::Instance().currentFG->Mutex.getOwner()); - State::Instance().currentFG->Mutex.unlockThis(3); } return result; @@ -601,13 +599,14 @@ HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::ResizeBuffers1(UINT BufferCoun // dlssg calls this from present it seems // don't try to get a mutex when present owns it while dlssg mod is enabled if (!(_localMutex.getOwner() == 4 && Config::Instance()->FGType.value_or_default() == FGType::Nukems)) - OwnedLockGuard lock(_localMutex, 2); + OwnedLockGuard(_localMutex, 2); #endif + std::optional lock; if (State::Instance().activeFgType == OptiFG && Config::Instance()->FGUseMutexForSwapchain.value_or_default()) { LOG_TRACE("Waiting ffxMutex 3, current: {}", State::Instance().currentFG->Mutex.getOwner()); - State::Instance().currentFG->Mutex.lock(3); + lock.emplace(State::Instance().currentFG->Mutex, 3); LOG_TRACE("Accuired ffxMutex: {}", State::Instance().currentFG->Mutex.getOwner()); } @@ -709,10 +708,9 @@ HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::ResizeBuffers1(UINT BufferCoun LOG_DEBUG("result: {0:X}", (UINT) result); - if (State::Instance().activeFgType == OptiFG && Config::Instance()->FGUseMutexForSwapchain.value_or_default()) + if (lock) { LOG_TRACE("Releasing ffxMutex: {}", State::Instance().currentFG->Mutex.getOwner()); - State::Instance().currentFG->Mutex.unlockThis(3); } return result; diff --git a/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp b/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp index c181f00c..7a14e500 100644 --- a/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp +++ b/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp @@ -1598,8 +1598,7 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_EvaluateFeature(ID3D12GraphicsCom if (fg->Mutex.getOwner() == 2) { LOG_TRACE("Waiting for present!"); - fg->Mutex.lock(4); - fg->Mutex.unlockThis(4); + OwnedLockGuard lock(fg->Mutex, 4); } bool allocatorReset = false;