1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-19 05:52:11 +01:00

[d3d9] Enumerate adapters by display

WPF expects us to return an adapter for every display attached otherwise
it decides to device reset every frame.

Closes #1459
This commit is contained in:
Joshua Ashton 2020-02-21 01:06:55 +00:00
parent d424fb87aa
commit 0e353895fd
5 changed files with 54 additions and 10 deletions

View File

@ -32,10 +32,12 @@ namespace dxvk {
D3D9Adapter::D3D9Adapter(
D3D9InterfaceEx* pParent,
Rc<DxvkAdapter> Adapter,
UINT Ordinal)
UINT Ordinal,
UINT DisplayIndex)
: m_parent (pParent)
, m_adapter (Adapter)
, m_ordinal (Ordinal)
, m_displayIndex (DisplayIndex)
, m_modeCacheFormat (D3D9Format::Unknown)
, m_d3d9Formats (Adapter, m_parent->GetOptions()) {
m_adapter->logAdapterInfo();
@ -52,11 +54,11 @@ namespace dxvk {
const auto& props = m_adapter->deviceProperties();
::MONITORINFOEXA monInfo;
monInfo.cbSize = sizeof(monInfo);
DISPLAY_DEVICEA device = { };
device.cb = sizeof(device);
if (!::GetMonitorInfoA(GetDefaultMonitor(), reinterpret_cast<MONITORINFO*>(&monInfo))) {
Logger::err("D3D9Adapter::GetAdapterIdentifier: Failed to query monitor info");
if (!::EnumDisplayDevicesA(nullptr, m_displayIndex, &device, 0)) {
Logger::err("D3D9Adapter::GetAdapterIdentifier: Failed to query display info");
return D3DERR_INVALIDCALL;
}
@ -68,7 +70,7 @@ namespace dxvk {
const char* driver = GetDriverDLL(DxvkGpuVendor(vendorId));
std::strncpy(pIdentifier->Description, desc, countof(pIdentifier->Description));
std::strncpy(pIdentifier->DeviceName, monInfo.szDevice, countof(pIdentifier->DeviceName)); // The GDI device name. Not the actual device name.
std::strncpy(pIdentifier->DeviceName, device.DeviceName, countof(pIdentifier->DeviceName)); // The GDI device name. Not the actual device name.
std::strncpy(pIdentifier->Driver, driver, countof(pIdentifier->Driver)); // This is the driver's dll.
pIdentifier->DeviceIdentifier = guid;

View File

@ -18,7 +18,8 @@ namespace dxvk {
D3D9Adapter(
D3D9InterfaceEx* pParent,
Rc<DxvkAdapter> Adapter,
UINT Ordinal);
UINT Ordinal,
UINT DisplayIndex);
HRESULT GetAdapterIdentifier(
DWORD Flags,
@ -101,6 +102,7 @@ namespace dxvk {
Rc<DxvkAdapter> m_adapter;
UINT m_ordinal;
UINT m_displayIndex;
std::vector<D3DDISPLAYMODEEX> m_modes;
D3D9Format m_modeCacheFormat;

View File

@ -12,9 +12,45 @@ namespace dxvk {
: m_instance ( new DxvkInstance() )
, m_extended ( bExtended )
, m_d3d9Options ( nullptr, m_instance->config() ) {
m_adapters.reserve(m_instance->adapterCount());
for (uint32_t i = 0; i < m_instance->adapterCount(); i++)
m_adapters.emplace_back(this, m_instance->enumAdapters(i), i);
// D3D9 doesn't enumerate adapters like physical adapters...
// only as connected displays.
// Let's create some "adapters" for the amount of displays we have.
// We'll go through and match up displays -> our adapters in order.
// If we run out of adapters, then we'll just make repeats of the first one.
// We can't match up by names on Linux/Wine as they don't match at all
// like on Windows, so this is our best option.
if (m_d3d9Options.enumerateByDisplays) {
DISPLAY_DEVICEA device = { };
device.cb = sizeof(device);
uint32_t adapterOrdinal = 0;
uint32_t i = 0;
while (::EnumDisplayDevicesA(nullptr, i++, &device, 0)) {
// If we aren't attached, skip over.
if (!(device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
continue;
// If we are a mirror, skip over this device.
if (device.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)
continue;
Rc<DxvkAdapter> adapter = adapterOrdinal >= m_instance->adapterCount()
? m_instance->enumAdapters(0)
: m_instance->enumAdapters(adapterOrdinal);
if (adapter != nullptr)
m_adapters.emplace_back(this, adapter, adapterOrdinal++, i - 1);
}
}
else
{
const uint32_t adapterCount = m_instance->adapterCount();
m_adapters.reserve(adapterCount);
for (uint32_t i = 0; i < adapterCount; i++)
m_adapters.emplace_back(this, m_instance->enumAdapters(i), i, 0);
}
if (m_d3d9Options.dpiAware) {
Logger::info("Process set as DPI aware");

View File

@ -67,6 +67,7 @@ namespace dxvk {
this->forceAspectRatio = config.getOption<std::string>("d3d9.forceAspectRatio", "");
this->allowDoNotWait = config.getOption<bool> ("d3d9.allowDoNotWait", true);
this->allowDiscard = config.getOption<bool> ("d3d9.allowDiscard", true);
this->enumerateByDisplays = config.getOption<bool> ("d3d9.enumerateByDisplays", true);
// If we are not Nvidia, enable general hazards.
this->generalHazards = adapter == nullptr || !adapter->matchesDriver(DxvkGpuVendor::Nvidia, VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR, 0, 0);

View File

@ -125,6 +125,9 @@ namespace dxvk {
/// Allow D3DLOCK_DISCARD
bool allowDiscard;
/// Enumerate adapters by displays
bool enumerateByDisplays;
};
}