[dxgi] Be more robust against monitor enumeration issues.

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.
This commit is contained in:
Philip Rebohle 2023-05-09 12:24:54 +02:00 committed by Philip Rebohle
parent 80f7d2abd8
commit 14eb469005
3 changed files with 61 additions and 8 deletions

View File

@ -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;
@ -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)

View File

@ -1,3 +1,5 @@
#include <algorithm>
#include "dxgi_factory.h"
#include "dxgi_surface.h"
#include "dxgi_swapchain.h"
@ -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");
}

View File

@ -158,6 +158,10 @@ namespace dxvk {
HRESULT STDMETHODCALLTYPE UnregisterAdaptersChangedEvent(
DWORD Cookie);
BOOL UseMonitorFallback() const {
return m_monitorFallback;
}
Rc<DxvkInstance> GetDXVKInstance() const {
return m_instance;
}
@ -177,6 +181,7 @@ namespace dxvk {
DxgiOptions m_options;
DxgiMonitorInfo m_monitorInfo;
UINT m_flags;
BOOL m_monitorFallback;
HWND m_associatedWindow = nullptr;