зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1201202 - Don't attempt to use WARP after D3D11CreateDevice crashes. r=bas, a=sylvestre
This commit is contained in:
Родитель
890d912075
Коммит
5856b7ba17
|
@ -16,6 +16,8 @@ FeatureStatusToString(FeatureStatus aStatus)
|
|||
return "unused";
|
||||
case FeatureStatus::Unavailable:
|
||||
return "unavailable";
|
||||
case FeatureStatus::Crashed:
|
||||
return "crashed";
|
||||
case FeatureStatus::Blocked:
|
||||
return "blocked";
|
||||
case FeatureStatus::Blacklisted:
|
||||
|
|
|
@ -21,6 +21,9 @@ enum class FeatureStatus
|
|||
// the operating system.
|
||||
Unavailable,
|
||||
|
||||
// This feature crashed immediately when we tried to initialize it.
|
||||
Crashed,
|
||||
|
||||
// This feature was blocked for reasons outside the blacklist, such as a
|
||||
// runtime test failing.
|
||||
Blocked,
|
||||
|
|
|
@ -510,12 +510,9 @@ gfxWindowsPlatform::HandleDeviceReset()
|
|||
}
|
||||
|
||||
// Remove devices and adapters.
|
||||
ResetD3D11Devices();
|
||||
mD3D10Device = nullptr;
|
||||
mD3D11Device = nullptr;
|
||||
mD3D11ContentDevice = nullptr;
|
||||
mD3D11ImageBridgeDevice = nullptr;
|
||||
mAdapter = nullptr;
|
||||
Factory::SetDirect3D11Device(nullptr);
|
||||
Factory::SetDirect3D10Device(nullptr);
|
||||
|
||||
// Reset local state. Note: we leave feature status variables as-is. They
|
||||
|
@ -1995,12 +1992,12 @@ gfxWindowsPlatform::CheckD3D11Support(bool* aCanUseHardware)
|
|||
// be used within InitializeD3D11.
|
||||
decltype(D3D11CreateDevice)* sD3D11CreateDeviceFn = nullptr;
|
||||
|
||||
void
|
||||
FeatureStatus
|
||||
gfxWindowsPlatform::AttemptD3D11DeviceCreation()
|
||||
{
|
||||
RefPtr<IDXGIAdapter1> adapter = GetDXGIAdapter();
|
||||
if (!adapter) {
|
||||
return;
|
||||
return FeatureStatus::Unavailable;
|
||||
}
|
||||
|
||||
HRESULT hr = E_INVALIDARG;
|
||||
|
@ -2015,16 +2012,20 @@ gfxWindowsPlatform::AttemptD3D11DeviceCreation()
|
|||
D3D11_SDK_VERSION, byRef(mD3D11Device), nullptr, nullptr);
|
||||
} MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
|
||||
gfxCriticalError() << "Crash during D3D11 device creation";
|
||||
return;
|
||||
return FeatureStatus::Crashed;
|
||||
}
|
||||
|
||||
if (FAILED(hr) || !DoesD3D11DeviceWork()) {
|
||||
gfxCriticalError() << "D3D11 device creation failed" << hexa(hr);
|
||||
if (FAILED(hr) || !mD3D11Device) {
|
||||
mD3D11Device = nullptr;
|
||||
return;
|
||||
gfxCriticalError() << "D3D11 device creation failed: " << hexa(hr);
|
||||
return FeatureStatus::Failed;
|
||||
}
|
||||
if (!DoesD3D11DeviceWork()) {
|
||||
mD3D11Device = nullptr;
|
||||
return FeatureStatus::Blocked;
|
||||
}
|
||||
if (!mD3D11Device) {
|
||||
return;
|
||||
return FeatureStatus::Failed;
|
||||
}
|
||||
|
||||
CheckIfRenderTargetViewNeedsRecreating(mD3D11Device);
|
||||
|
@ -2034,9 +2035,10 @@ gfxWindowsPlatform::AttemptD3D11DeviceCreation()
|
|||
mCompositorD3D11TextureSharingWorks = ::DoesD3D11TextureSharingWork(mD3D11Device);
|
||||
mD3D11Device->SetExceptionMode(0);
|
||||
mIsWARP = false;
|
||||
return FeatureStatus::Available;
|
||||
}
|
||||
|
||||
void
|
||||
FeatureStatus
|
||||
gfxWindowsPlatform::AttemptWARPDeviceCreation()
|
||||
{
|
||||
ScopedGfxFeatureReporter reporterWARP("D3D11-WARP", gfxPrefs::LayersD3D11ForceWARP());
|
||||
|
@ -2054,14 +2056,13 @@ gfxWindowsPlatform::AttemptWARPDeviceCreation()
|
|||
if (FAILED(hr)) {
|
||||
// This should always succeed... in theory.
|
||||
gfxCriticalError() << "Failed to initialize WARP D3D11 device! " << hexa(hr);
|
||||
return;
|
||||
return FeatureStatus::Failed;
|
||||
}
|
||||
|
||||
reporterWARP.SetSuccessful();
|
||||
} MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
|
||||
gfxCriticalError() << "Exception occurred initializing WARP D3D11 device!";
|
||||
return;
|
||||
|
||||
return FeatureStatus::Crashed;
|
||||
}
|
||||
|
||||
// Only test for texture sharing on Windows 8 since it puts the device into
|
||||
|
@ -2071,6 +2072,7 @@ gfxWindowsPlatform::AttemptWARPDeviceCreation()
|
|||
}
|
||||
mD3D11Device->SetExceptionMode(0);
|
||||
mIsWARP = true;
|
||||
return FeatureStatus::Available;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -2096,14 +2098,14 @@ gfxWindowsPlatform::ContentAdapterIsParentAdapter(ID3D11Device* device)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
FeatureStatus
|
||||
gfxWindowsPlatform::AttemptD3D11ContentDeviceCreation()
|
||||
{
|
||||
RefPtr<IDXGIAdapter1> adapter;
|
||||
if (!mIsWARP) {
|
||||
adapter = GetDXGIAdapter();
|
||||
if (!adapter) {
|
||||
return false;
|
||||
return FeatureStatus::Unavailable;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2117,11 +2119,11 @@ gfxWindowsPlatform::AttemptD3D11ContentDeviceCreation()
|
|||
mFeatureLevels.Elements(), mFeatureLevels.Length(),
|
||||
D3D11_SDK_VERSION, byRef(mD3D11ContentDevice), nullptr, nullptr);
|
||||
} MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
|
||||
return false;
|
||||
return FeatureStatus::Crashed;
|
||||
}
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
return FeatureStatus::Failed;
|
||||
}
|
||||
|
||||
// InitializeD2D() will abort early if the compositor device did not support
|
||||
|
@ -2135,7 +2137,7 @@ gfxWindowsPlatform::AttemptD3D11ContentDeviceCreation()
|
|||
!ContentAdapterIsParentAdapter(mD3D11ContentDevice))
|
||||
{
|
||||
mD3D11ContentDevice = nullptr;
|
||||
return false;
|
||||
return FeatureStatus::Failed;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2146,10 +2148,10 @@ gfxWindowsPlatform::AttemptD3D11ContentDeviceCreation()
|
|||
multi->SetMultithreadProtected(TRUE);
|
||||
|
||||
Factory::SetDirect3D11Device(mD3D11ContentDevice);
|
||||
return true;
|
||||
return FeatureStatus::Available;
|
||||
}
|
||||
|
||||
void
|
||||
FeatureStatus
|
||||
gfxWindowsPlatform::AttemptD3D11ImageBridgeDeviceCreation()
|
||||
{
|
||||
HRESULT hr = E_INVALIDARG;
|
||||
|
@ -2160,11 +2162,11 @@ gfxWindowsPlatform::AttemptD3D11ImageBridgeDeviceCreation()
|
|||
mFeatureLevels.Elements(), mFeatureLevels.Length(),
|
||||
D3D11_SDK_VERSION, byRef(mD3D11ImageBridgeDevice), nullptr, nullptr);
|
||||
} MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
||||
return;
|
||||
return FeatureStatus::Crashed;
|
||||
}
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return;
|
||||
return FeatureStatus::Failed;
|
||||
}
|
||||
|
||||
mD3D11ImageBridgeDevice->SetExceptionMode(0);
|
||||
|
@ -2172,8 +2174,9 @@ gfxWindowsPlatform::AttemptD3D11ImageBridgeDeviceCreation()
|
|||
(XRE_IsContentProcess() && !ContentAdapterIsParentAdapter(mD3D11ImageBridgeDevice)))
|
||||
{
|
||||
mD3D11ImageBridgeDevice = nullptr;
|
||||
return;
|
||||
return FeatureStatus::Failed;
|
||||
}
|
||||
return FeatureStatus::Available;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2283,31 +2286,43 @@ gfxWindowsPlatform::InitializeD3D11()
|
|||
if (XRE_IsParentProcess()) {
|
||||
// First try to create a hardware accelerated device.
|
||||
if (canUseHardware) {
|
||||
AttemptD3D11DeviceCreation();
|
||||
mD3D11Status = AttemptD3D11DeviceCreation();
|
||||
if (mD3D11Status == FeatureStatus::Crashed) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If that failed, see if we can use WARP.
|
||||
if (!mD3D11Device && CanUseWARP()) {
|
||||
AttemptWARPDeviceCreation();
|
||||
if (!mD3D11Device) {
|
||||
if (!CanUseWARP()) {
|
||||
mD3D11Status = FeatureStatus::Blocked;
|
||||
return;
|
||||
}
|
||||
mD3D11Status = AttemptWARPDeviceCreation();
|
||||
}
|
||||
|
||||
// If we still have no device by now, exit.
|
||||
if (!mD3D11Device) {
|
||||
// Nothing more we can do.
|
||||
mD3D11Status = FeatureStatus::Failed;
|
||||
MOZ_ASSERT(IsFeatureStatusFailure(mD3D11Status));
|
||||
return;
|
||||
}
|
||||
|
||||
// Either device creation function should have returned Available.
|
||||
MOZ_ASSERT(mD3D11Status == FeatureStatus::Available);
|
||||
} else {
|
||||
// Child processes do not need a compositor, but they do need to know
|
||||
// whether the parent process is using WARP and whether or not texture
|
||||
// sharing works.
|
||||
mIsWARP = !canUseHardware;
|
||||
mCompositorD3D11TextureSharingWorks = GetParentDevicePrefs().d3d11TextureSharingWorks();
|
||||
mD3D11Status = FeatureStatus::Available;
|
||||
}
|
||||
|
||||
mD3D11Status = FeatureStatus::Available;
|
||||
|
||||
if (CanUseD3D11ImageBridge()) {
|
||||
AttemptD3D11ImageBridgeDeviceCreation();
|
||||
if (AttemptD3D11ImageBridgeDeviceCreation() == FeatureStatus::Crashed) {
|
||||
DisableD3D11AfterCrash();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// We leak these everywhere and we need them our entire runtime anyway, let's
|
||||
|
@ -2316,6 +2331,22 @@ gfxWindowsPlatform::InitializeD3D11()
|
|||
d3d11Module.disown();
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsPlatform::DisableD3D11AfterCrash()
|
||||
{
|
||||
mD3D11Status = FeatureStatus::Crashed;
|
||||
ResetD3D11Devices();
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsPlatform::ResetD3D11Devices()
|
||||
{
|
||||
mD3D11Device = nullptr;
|
||||
mD3D11ContentDevice = nullptr;
|
||||
mD3D11ImageBridgeDevice = nullptr;
|
||||
Factory::SetDirect3D11Device(nullptr);
|
||||
}
|
||||
|
||||
static bool
|
||||
IsD2DBlacklisted()
|
||||
{
|
||||
|
@ -2434,12 +2465,15 @@ gfxWindowsPlatform::InitializeD2D1()
|
|||
return;
|
||||
}
|
||||
|
||||
if (!AttemptD3D11ContentDeviceCreation()) {
|
||||
mD2D1Status = FeatureStatus::Failed;
|
||||
mD2D1Status = AttemptD3D11ContentDeviceCreation();
|
||||
if (IsFeatureStatusFailure(mD2D1Status)) {
|
||||
if (mD2D1Status == FeatureStatus::Crashed) {
|
||||
DisableD3D11AfterCrash();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mD2D1Status = FeatureStatus::Available;
|
||||
MOZ_ASSERT(mD2D1Status == FeatureStatus::Available);
|
||||
d2d1_1.SetSuccessful();
|
||||
}
|
||||
|
||||
|
|
|
@ -318,13 +318,16 @@ private:
|
|||
mozilla::gfx::FeatureStatus CheckD3D11Support(bool* aCanUseHardware);
|
||||
mozilla::gfx::FeatureStatus CheckD2DSupport();
|
||||
mozilla::gfx::FeatureStatus CheckD2D1Support();
|
||||
void AttemptD3D11DeviceCreation();
|
||||
void AttemptWARPDeviceCreation();
|
||||
void AttemptD3D11ImageBridgeDeviceCreation();
|
||||
bool AttemptD3D11ContentDeviceCreation();
|
||||
mozilla::gfx::FeatureStatus AttemptD3D11DeviceCreation();
|
||||
mozilla::gfx::FeatureStatus AttemptWARPDeviceCreation();
|
||||
mozilla::gfx::FeatureStatus AttemptD3D11ImageBridgeDeviceCreation();
|
||||
mozilla::gfx::FeatureStatus AttemptD3D11ContentDeviceCreation();
|
||||
bool CanUseD3D11ImageBridge();
|
||||
bool ContentAdapterIsParentAdapter(ID3D11Device* device);
|
||||
|
||||
void DisableD3D11AfterCrash();
|
||||
void ResetD3D11Devices();
|
||||
|
||||
IDXGIAdapter1 *GetDXGIAdapter();
|
||||
bool IsDeviceReset(HRESULT hr, DeviceResetReason* aReason);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче