From b428af7892e7e90248c7cedb7bd485104c3cb833 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 10 Aug 2015 20:27:06 -0700 Subject: [PATCH] Don't mix GPU adapters across processes. (bug 1183910 part 10, r=jmuizelaar) --- gfx/ipc/GraphicsMessages.ipdlh | 15 ++++++ gfx/thebes/gfxWindowsPlatform.cpp | 82 +++++++++++++++++++++++++------ gfx/thebes/gfxWindowsPlatform.h | 1 + 3 files changed, 83 insertions(+), 15 deletions(-) diff --git a/gfx/ipc/GraphicsMessages.ipdlh b/gfx/ipc/GraphicsMessages.ipdlh index eef1fe22eb4..a7e21b99cb3 100644 --- a/gfx/ipc/GraphicsMessages.ipdlh +++ b/gfx/ipc/GraphicsMessages.ipdlh @@ -8,6 +8,20 @@ namespace mozilla { namespace gfx { +struct DxgiLUID +{ + uint32_t LowPart; + int32_t HighPart; +}; + +struct DxgiDesc +{ + uint32_t vendorID; + uint32_t deviceID; + uint32_t subSysID; + DxgiLUID luid; +}; + struct DeviceInitData { bool useAcceleration; @@ -19,6 +33,7 @@ struct DeviceInitData bool d3d11TextureSharingWorks; bool useD2D; bool useD2D1; + DxgiDesc dxgiDesc; }; } // namespace gfx diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index 3ca3702e688..ddd22661372 100755 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -1708,25 +1708,35 @@ bool DoesD3D11DeviceWork(ID3D11Device *device) return true; } +static bool +GetDxgiDesc(ID3D11Device* device, DXGI_ADAPTER_DESC* out) +{ + nsRefPtr dxgiDevice; + HRESULT hr = device->QueryInterface(__uuidof(IDXGIDevice), getter_AddRefs(dxgiDevice)); + if (FAILED(hr)) { + return false; + } + + nsRefPtr dxgiAdapter; + if (FAILED(dxgiDevice->GetAdapter(getter_AddRefs(dxgiAdapter)))) { + return false; + } + + return SUCCEEDED(dxgiAdapter->GetDesc(out)); +} + static void CheckForAdapterMismatch(ID3D11Device *device) { - nsRefPtr dxgiDevice; - if (FAILED(device->QueryInterface(__uuidof(IDXGIDevice), - getter_AddRefs(dxgiDevice)))) { - return; - } - nsRefPtr dxgiAdapter; - if (FAILED(dxgiDevice->GetAdapter(getter_AddRefs(dxgiAdapter)))) { - return; - } + DXGI_ADAPTER_DESC desc; + PodZero(&desc); + GetDxgiDesc(device, &desc); + nsCOMPtr gfxInfo = services::GetGfxInfo(); nsString vendorID; gfxInfo->GetAdapterVendorID(vendorID); nsresult ec; int32_t vendor = vendorID.ToInteger(&ec, 16); - DXGI_ADAPTER_DESC desc; - dxgiAdapter->GetDesc(&desc); if (vendor != desc.VendorId) { gfxCriticalNote << "VendorIDMismatch " << hexa(vendor) << " " << hexa(desc.VendorId); } @@ -2051,6 +2061,29 @@ gfxWindowsPlatform::AttemptWARPDeviceCreation() mIsWARP = true; } +bool +gfxWindowsPlatform::ContentAdapterIsParentAdapter(ID3D11Device* device) +{ + DXGI_ADAPTER_DESC desc; + if (!GetDxgiDesc(device, &desc)) { + gfxCriticalNote << "Could not query device DXGI adapter info"; + return false; + } + + const DxgiDesc& parent = GetParentDevicePrefs().dxgiDesc(); + if (desc.VendorId != parent.vendorID() || + desc.DeviceId != parent.deviceID() || + desc.SubSysId != parent.subSysID() || + desc.AdapterLuid.HighPart != parent.luid().HighPart() || + desc.AdapterLuid.LowPart != parent.luid().LowPart()) + { + gfxCriticalNote << "VendorIDMismatch " << hexa(parent.vendorID()) << " " << hexa(desc.VendorId); + return false; + } + + return true; +} + bool gfxWindowsPlatform::AttemptD3D11ContentDeviceCreation() { @@ -2085,9 +2118,13 @@ gfxWindowsPlatform::AttemptD3D11ContentDeviceCreation() // binding the parent and child processes to different GPUs. As a safety net, // we re-check texture sharing against the newly created D3D11 content device. // If it fails, we won't use Direct2D. - if (XRE_IsContentProcess() && !DoesD3D11TextureSharingWork(mD3D11ContentDevice)) { - mD3D11ContentDevice = nullptr; - return false; + if (XRE_IsContentProcess()) { + if (!DoesD3D11TextureSharingWork(mD3D11ContentDevice) || + !ContentAdapterIsParentAdapter(mD3D11ContentDevice)) + { + mD3D11ContentDevice = nullptr; + return false; + } } mD3D11ContentDevice->SetExceptionMode(0); @@ -2119,7 +2156,9 @@ gfxWindowsPlatform::AttemptD3D11ImageBridgeDeviceCreation() } mD3D11ImageBridgeDevice->SetExceptionMode(0); - if (!DoesD3D11AlphaTextureSharingWork(mD3D11ImageBridgeDevice)) { + if (!DoesD3D11AlphaTextureSharingWork(mD3D11ImageBridgeDevice) || + (XRE_IsContentProcess() && !ContentAdapterIsParentAdapter(mD3D11ImageBridgeDevice))) + { mD3D11ImageBridgeDevice = nullptr; return; } @@ -2725,4 +2764,17 @@ gfxWindowsPlatform::GetDeviceInitData(DeviceInitData* aOut) aOut->useD3D11WARP() = mIsWARP; aOut->useD2D() = (GetD2DStatus() == FeatureStatus::Available); aOut->useD2D1() = (GetD2D1Status() == FeatureStatus::Available); + + if (mD3D11Device) { + DXGI_ADAPTER_DESC desc; + if (!GetDxgiDesc(mD3D11Device, &desc)) { + return; + } + + aOut->dxgiDesc().vendorID() = desc.VendorId; + aOut->dxgiDesc().deviceID() = desc.DeviceId; + aOut->dxgiDesc().subSysID() = desc.SubSysId; + aOut->dxgiDesc().luid().LowPart() = desc.AdapterLuid.LowPart; + aOut->dxgiDesc().luid().HighPart() = desc.AdapterLuid.HighPart; + } } diff --git a/gfx/thebes/gfxWindowsPlatform.h b/gfx/thebes/gfxWindowsPlatform.h index 082bdfb95d5..99111090fcb 100644 --- a/gfx/thebes/gfxWindowsPlatform.h +++ b/gfx/thebes/gfxWindowsPlatform.h @@ -323,6 +323,7 @@ private: void AttemptD3D11ImageBridgeDeviceCreation(); bool AttemptD3D11ContentDeviceCreation(); bool CanUseD3D11ImageBridge(); + bool ContentAdapterIsParentAdapter(ID3D11Device* device); IDXGIAdapter1 *GetDXGIAdapter(); bool IsDeviceReset(HRESULT hr, DeviceResetReason* aReason);