Skip to content

Commit

Permalink
[dxgi] Be more robust against monitor enumeration issues.
Browse files Browse the repository at this point in the history
If there are monitors on the system that are not associated with
any adapter, enumerate all monitors for all adatpers. May solve
some issues if device filter options are used on multi-GPU systems.
  • Loading branch information
doitsujin committed May 11, 2023
1 parent 80f7d2a commit 14eb469
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 8 deletions.
6 changes: 5 additions & 1 deletion src/dxgi/dxgi_adapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ namespace dxvk {

auto linkedAdapter = m_adapter->linkedIGPUAdapter();

/* If either LUID is not valid enumerate all monitors. */
// If either LUID is not valid, enumerate all monitors.
if (numLUIDs && linkedAdapter != nullptr) {
const auto& deviceId = linkedAdapter->devicePropertiesExt().vk11;

Expand All @@ -172,6 +172,10 @@ namespace dxvk {
numLUIDs = 0;
}

// Enumerate all monitors if the robustness fallback is active.
if (m_factory->UseMonitorFallback())
numLUIDs = 0;

HMONITOR monitor = wsi::enumMonitors(adapterLUIDs.data(), numLUIDs, Output);

if (monitor == nullptr)
Expand Down
58 changes: 51 additions & 7 deletions src/dxgi/dxgi_factory.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include <algorithm>

#include "dxgi_factory.h"
#include "dxgi_surface.h"
#include "dxgi_swapchain.h"
Expand Down Expand Up @@ -48,13 +50,55 @@ namespace dxvk {


DxgiFactory::DxgiFactory(UINT Flags)
: m_instance (g_dxvkInstance.acquire()),
m_interop (this),
m_options (m_instance->config()),
m_monitorInfo (this, m_options),
m_flags (Flags) {
for (uint32_t i = 0; m_instance->enumAdapters(i) != nullptr; i++)
m_instance->enumAdapters(i)->logAdapterInfo();
: m_instance (g_dxvkInstance.acquire()),
m_interop (this),
m_options (m_instance->config()),
m_monitorInfo (this, m_options),
m_flags (Flags),
m_monitorFallback (false) {
// Be robust against situations where some monitors are not
// associated with any adapter. This can happen if device
// filter options are used.
std::vector<HMONITOR> monitors;

for (uint32_t i = 0; ; i++) {
HMONITOR hmon = wsi::enumMonitors(i);

if (!hmon)
break;

monitors.push_back(hmon);
}

for (uint32_t i = 0; m_instance->enumAdapters(i) != nullptr; i++) {
auto adapter = m_instance->enumAdapters(i);
adapter->logAdapterInfo();

// Remove all monitors that are associated
// with the current adapter from the list.
const auto& vk11 = adapter->devicePropertiesExt().vk11;

if (vk11.deviceLUIDValid) {
auto luid = reinterpret_cast<const LUID*>(&vk11.deviceLUID);

for (uint32_t j = 0; ; j++) {
HMONITOR hmon = wsi::enumMonitors(&luid, 1, j);

if (!hmon)
break;

auto entry = std::find(monitors.begin(), monitors.end(), hmon);

if (entry != monitors.end())
monitors.erase(entry);
}
}
}

// If any monitors are left on the list, enable the
// fallback to always enumerate all monitors.
if ((m_monitorFallback = !monitors.empty()))
Logger::warn("DXGI: Found monitors not associated with any adapter, using fallback");
}


Expand Down
5 changes: 5 additions & 0 deletions src/dxgi/dxgi_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,10 @@ namespace dxvk {
HRESULT STDMETHODCALLTYPE UnregisterAdaptersChangedEvent(
DWORD Cookie);

BOOL UseMonitorFallback() const {
return m_monitorFallback;
}

Rc<DxvkInstance> GetDXVKInstance() const {
return m_instance;
}
Expand All @@ -177,6 +181,7 @@ namespace dxvk {
DxgiOptions m_options;
DxgiMonitorInfo m_monitorInfo;
UINT m_flags;
BOOL m_monitorFallback;

HWND m_associatedWindow = nullptr;

Expand Down

0 comments on commit 14eb469

Please sign in to comment.