Don't mix GPU adapters across processes. (bug 1183910 part 10, r=jmuizelaar)

This commit is contained in:
David Anderson 2015-08-10 20:27:06 -07:00
parent 0739f752c2
commit b428af7892
3 changed files with 83 additions and 15 deletions

View File

@ -8,6 +8,20 @@
namespace mozilla { namespace mozilla {
namespace gfx { 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 struct DeviceInitData
{ {
bool useAcceleration; bool useAcceleration;
@ -19,6 +33,7 @@ struct DeviceInitData
bool d3d11TextureSharingWorks; bool d3d11TextureSharingWorks;
bool useD2D; bool useD2D;
bool useD2D1; bool useD2D1;
DxgiDesc dxgiDesc;
}; };
} // namespace gfx } // namespace gfx

View File

@ -1708,25 +1708,35 @@ bool DoesD3D11DeviceWork(ID3D11Device *device)
return true; return true;
} }
static bool
GetDxgiDesc(ID3D11Device* device, DXGI_ADAPTER_DESC* out)
{
nsRefPtr<IDXGIDevice> dxgiDevice;
HRESULT hr = device->QueryInterface(__uuidof(IDXGIDevice), getter_AddRefs(dxgiDevice));
if (FAILED(hr)) {
return false;
}
nsRefPtr<IDXGIAdapter> dxgiAdapter;
if (FAILED(dxgiDevice->GetAdapter(getter_AddRefs(dxgiAdapter)))) {
return false;
}
return SUCCEEDED(dxgiAdapter->GetDesc(out));
}
static void static void
CheckForAdapterMismatch(ID3D11Device *device) CheckForAdapterMismatch(ID3D11Device *device)
{ {
nsRefPtr<IDXGIDevice> dxgiDevice; DXGI_ADAPTER_DESC desc;
if (FAILED(device->QueryInterface(__uuidof(IDXGIDevice), PodZero(&desc);
getter_AddRefs(dxgiDevice)))) { GetDxgiDesc(device, &desc);
return;
}
nsRefPtr<IDXGIAdapter> dxgiAdapter;
if (FAILED(dxgiDevice->GetAdapter(getter_AddRefs(dxgiAdapter)))) {
return;
}
nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo(); nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
nsString vendorID; nsString vendorID;
gfxInfo->GetAdapterVendorID(vendorID); gfxInfo->GetAdapterVendorID(vendorID);
nsresult ec; nsresult ec;
int32_t vendor = vendorID.ToInteger(&ec, 16); int32_t vendor = vendorID.ToInteger(&ec, 16);
DXGI_ADAPTER_DESC desc;
dxgiAdapter->GetDesc(&desc);
if (vendor != desc.VendorId) { if (vendor != desc.VendorId) {
gfxCriticalNote << "VendorIDMismatch " << hexa(vendor) << " " << hexa(desc.VendorId); gfxCriticalNote << "VendorIDMismatch " << hexa(vendor) << " " << hexa(desc.VendorId);
} }
@ -2051,6 +2061,29 @@ gfxWindowsPlatform::AttemptWARPDeviceCreation()
mIsWARP = true; 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 bool
gfxWindowsPlatform::AttemptD3D11ContentDeviceCreation() gfxWindowsPlatform::AttemptD3D11ContentDeviceCreation()
{ {
@ -2085,9 +2118,13 @@ gfxWindowsPlatform::AttemptD3D11ContentDeviceCreation()
// binding the parent and child processes to different GPUs. As a safety net, // 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. // we re-check texture sharing against the newly created D3D11 content device.
// If it fails, we won't use Direct2D. // If it fails, we won't use Direct2D.
if (XRE_IsContentProcess() && !DoesD3D11TextureSharingWork(mD3D11ContentDevice)) { if (XRE_IsContentProcess()) {
mD3D11ContentDevice = nullptr; if (!DoesD3D11TextureSharingWork(mD3D11ContentDevice) ||
return false; !ContentAdapterIsParentAdapter(mD3D11ContentDevice))
{
mD3D11ContentDevice = nullptr;
return false;
}
} }
mD3D11ContentDevice->SetExceptionMode(0); mD3D11ContentDevice->SetExceptionMode(0);
@ -2119,7 +2156,9 @@ gfxWindowsPlatform::AttemptD3D11ImageBridgeDeviceCreation()
} }
mD3D11ImageBridgeDevice->SetExceptionMode(0); mD3D11ImageBridgeDevice->SetExceptionMode(0);
if (!DoesD3D11AlphaTextureSharingWork(mD3D11ImageBridgeDevice)) { if (!DoesD3D11AlphaTextureSharingWork(mD3D11ImageBridgeDevice) ||
(XRE_IsContentProcess() && !ContentAdapterIsParentAdapter(mD3D11ImageBridgeDevice)))
{
mD3D11ImageBridgeDevice = nullptr; mD3D11ImageBridgeDevice = nullptr;
return; return;
} }
@ -2725,4 +2764,17 @@ gfxWindowsPlatform::GetDeviceInitData(DeviceInitData* aOut)
aOut->useD3D11WARP() = mIsWARP; aOut->useD3D11WARP() = mIsWARP;
aOut->useD2D() = (GetD2DStatus() == FeatureStatus::Available); aOut->useD2D() = (GetD2DStatus() == FeatureStatus::Available);
aOut->useD2D1() = (GetD2D1Status() == 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;
}
} }

View File

@ -323,6 +323,7 @@ private:
void AttemptD3D11ImageBridgeDeviceCreation(); void AttemptD3D11ImageBridgeDeviceCreation();
bool AttemptD3D11ContentDeviceCreation(); bool AttemptD3D11ContentDeviceCreation();
bool CanUseD3D11ImageBridge(); bool CanUseD3D11ImageBridge();
bool ContentAdapterIsParentAdapter(ID3D11Device* device);
IDXGIAdapter1 *GetDXGIAdapter(); IDXGIAdapter1 *GetDXGIAdapter();
bool IsDeviceReset(HRESULT hr, DeviceResetReason* aReason); bool IsDeviceReset(HRESULT hr, DeviceResetReason* aReason);