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 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

View File

@ -1708,25 +1708,35 @@ bool DoesD3D11DeviceWork(ID3D11Device *device)
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
CheckForAdapterMismatch(ID3D11Device *device)
{
nsRefPtr<IDXGIDevice> dxgiDevice;
if (FAILED(device->QueryInterface(__uuidof(IDXGIDevice),
getter_AddRefs(dxgiDevice)))) {
return;
}
nsRefPtr<IDXGIAdapter> dxgiAdapter;
if (FAILED(dxgiDevice->GetAdapter(getter_AddRefs(dxgiAdapter)))) {
return;
}
DXGI_ADAPTER_DESC desc;
PodZero(&desc);
GetDxgiDesc(device, &desc);
nsCOMPtr<nsIGfxInfo> 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,10 +2118,14 @@ 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)) {
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;
}
}

View File

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