From 079cda1c0ce225be3db68a39383de47904e67cfd Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Fri, 3 Apr 2020 02:04:17 +0200 Subject: [PATCH] [dxgi] Implement RegisterVideoMemoryBudgetChangeNotificationEvent Closes #1544. --- src/dxgi/dxgi_adapter.cpp | 60 ++++++++++++++++++++++++++++++++++++--- src/dxgi/dxgi_adapter.h | 9 ++++++ 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/src/dxgi/dxgi_adapter.cpp b/src/dxgi/dxgi_adapter.cpp index abce251b..4cf72e4c 100644 --- a/src/dxgi/dxgi_adapter.cpp +++ b/src/dxgi/dxgi_adapter.cpp @@ -66,7 +66,14 @@ namespace dxvk { DxgiAdapter::~DxgiAdapter() { - + if (m_eventThread.joinable()) { + std::unique_lock lock(m_mutex); + m_eventCookie = ~0u; + m_cond.notify_one(); + + lock.unlock(); + m_eventThread.join(); + } } @@ -349,8 +356,23 @@ namespace dxvk { HRESULT STDMETHODCALLTYPE DxgiAdapter::RegisterVideoMemoryBudgetChangeNotificationEvent( HANDLE hEvent, DWORD* pdwCookie) { - Logger::err("DxgiAdapter::RegisterVideoMemoryBudgetChangeNotificationEvent: Not implemented"); - return E_NOTIMPL; + if (!hEvent || !pdwCookie) + return E_INVALIDARG; + + std::unique_lock lock(m_mutex); + DWORD cookie = ++m_eventCookie; + + m_eventMap.insert({ cookie, hEvent }); + + if (!m_eventThread.joinable()) + m_eventThread = dxvk::thread([this] { runEventThread(); }); + + // This method seems to fire the + // event immediately on Windows + SetEvent(hEvent); + + *pdwCookie = cookie; + return S_OK; } @@ -362,7 +384,8 @@ namespace dxvk { void STDMETHODCALLTYPE DxgiAdapter::UnregisterVideoMemoryBudgetChangeNotification( DWORD dwCookie) { - Logger::err("DxgiAdapter::UnregisterVideoMemoryBudgetChangeNotification: Not implemented"); + std::unique_lock lock(m_mutex); + m_eventMap.erase(dwCookie); } @@ -374,5 +397,34 @@ namespace dxvk { Rc STDMETHODCALLTYPE DxgiAdapter::GetDXVKInstance() { return m_factory->GetDXVKInstance(); } + + + void DxgiAdapter::runEventThread() { + std::unique_lock lock(m_mutex); + DxvkAdapterMemoryInfo memoryInfoOld = m_adapter->getMemoryHeapInfo(); + + while (true) { + m_cond.wait_for(lock, std::chrono::milliseconds(1500), + [this] { return m_eventCookie == ~0u; }); + + if (m_eventCookie == ~0u) + return; + + auto memoryInfoNew = m_adapter->getMemoryHeapInfo(); + bool budgetChanged = false; + + for (uint32_t i = 0; i < memoryInfoNew.heapCount; i++) { + budgetChanged |= memoryInfoNew.heaps[i].memoryBudget + != memoryInfoOld.heaps[i].memoryBudget; + } + + if (budgetChanged) { + memoryInfoOld = memoryInfoNew; + + for (const auto& pair : m_eventMap) + SetEvent(pair.second); + } + } + } } diff --git a/src/dxgi/dxgi_adapter.h b/src/dxgi/dxgi_adapter.h index ecc2e7d8..864a55d9 100644 --- a/src/dxgi/dxgi_adapter.h +++ b/src/dxgi/dxgi_adapter.h @@ -111,6 +111,15 @@ namespace dxvk { UINT m_index; UINT64 m_memReservation[2] = { 0, 0 }; + + std::mutex m_mutex; + std::condition_variable m_cond; + + DWORD m_eventCookie = 0; + std::unordered_map m_eventMap; + dxvk::thread m_eventThread; + + void runEventThread(); };