Commit 276a3fcf by Jamie Madill Committed by Shannon Woods

Fix device removed handling for systems which do not

immediately allow recreating a new device. On Intel systems there's a cool-down period when you must wait before recreating the device. BUG=313210 Change-Id: I22cdf41eecf0eae5058b59e1b0863173d604d606
parent b66fd40e
...@@ -2115,7 +2115,7 @@ bool Renderer9::testDeviceResettable() ...@@ -2115,7 +2115,7 @@ bool Renderer9::testDeviceResettable()
return (mDeviceEx != NULL); return (mDeviceEx != NULL);
case D3DERR_DEVICEREMOVED: case D3DERR_DEVICEREMOVED:
ASSERT(mDeviceEx != NULL); ASSERT(mDeviceEx != NULL);
return true; return isRemovedDeviceResettable();
default: default:
return false; return false;
} }
...@@ -2129,23 +2129,26 @@ bool Renderer9::resetDevice() ...@@ -2129,23 +2129,26 @@ bool Renderer9::resetDevice()
HRESULT result = D3D_OK; HRESULT result = D3D_OK;
bool lost = testDeviceLost(false); bool lost = testDeviceLost(false);
int attempts = 3;
bool removedDevice = (getDeviceStatusCode() == D3DERR_DEVICEREMOVED); bool removedDevice = (getDeviceStatusCode() == D3DERR_DEVICEREMOVED);
while (lost && attempts > 0) // Device Removed is a feature which is only present with D3D9Ex
ASSERT(mDeviceEx != NULL || !removedDevice);
for (int attempts = 3; lost && attempts > 0; attempts--)
{ {
if (mDeviceEx) if (removedDevice)
{
// Device removed, which may trigger on driver reinstallation,
// may cause a longer wait other reset attempts before the
// system is ready to handle creating a new device.
Sleep(800);
lost = !resetRemovedDevice();
}
else if (mDeviceEx)
{ {
Sleep(500); // Give the graphics driver some CPU time Sleep(500); // Give the graphics driver some CPU time
result = mDeviceEx->ResetEx(&presentParameters, NULL);
if (removedDevice) lost = testDeviceLost(false);
{
result = resetRemovedDevice();
}
else
{
result = mDeviceEx->ResetEx(&presentParameters, NULL);
}
} }
else else
{ {
...@@ -2160,10 +2163,8 @@ bool Renderer9::resetDevice() ...@@ -2160,10 +2163,8 @@ bool Renderer9::resetDevice()
{ {
result = mDevice->Reset(&presentParameters); result = mDevice->Reset(&presentParameters);
} }
lost = testDeviceLost(false);
} }
lost = testDeviceLost(false);
attempts --;
} }
if (FAILED(result)) if (FAILED(result))
...@@ -2172,6 +2173,12 @@ bool Renderer9::resetDevice() ...@@ -2172,6 +2173,12 @@ bool Renderer9::resetDevice()
return false; return false;
} }
if (removedDevice && lost)
{
ERR("Device lost reset failed multiple times");
return false;
}
// If the device was removed, we already finished re-initialization in resetRemovedDevice // If the device was removed, we already finished re-initialization in resetRemovedDevice
if (!removedDevice) if (!removedDevice)
{ {
...@@ -2184,15 +2191,38 @@ bool Renderer9::resetDevice() ...@@ -2184,15 +2191,38 @@ bool Renderer9::resetDevice()
return true; return true;
} }
HRESULT Renderer9::resetRemovedDevice() bool Renderer9::isRemovedDeviceResettable() const
{
bool success = false;
#ifdef ANGLE_ENABLE_D3D9EX
IDirect3D9Ex *d3d9Ex = NULL;
typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**);
Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
if (Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &d3d9Ex)))
{
D3DCAPS9 deviceCaps;
HRESULT result = d3d9Ex->GetDeviceCaps(mAdapter, mDeviceType, &deviceCaps);
success = SUCCEEDED(result);
}
SafeRelease(d3d9Ex);
#else
ASSERT(UNREACHABLE());
#endif
return success;
}
bool Renderer9::resetRemovedDevice()
{ {
// From http://msdn.microsoft.com/en-us/library/windows/desktop/bb172554(v=vs.85).aspx: // From http://msdn.microsoft.com/en-us/library/windows/desktop/bb172554(v=vs.85).aspx:
// The hardware adapter has been removed. Application must destroy the device, do enumeration of // The hardware adapter has been removed. Application must destroy the device, do enumeration of
// adapters and create another Direct3D device. If application continues rendering without // adapters and create another Direct3D device. If application continues rendering without
// calling Reset, the rendering calls will succeed. Applies to Direct3D 9Ex only. // calling Reset, the rendering calls will succeed. Applies to Direct3D 9Ex only.
ASSERT(mDeviceEx != NULL);
deinitialize(); deinitialize();
return (initialize() == EGL_SUCCESS ? S_OK : S_FALSE); return (initialize() == EGL_SUCCESS);
} }
DWORD Renderer9::getAdapterVendor() const DWORD Renderer9::getAdapterVendor() const
......
...@@ -221,7 +221,8 @@ class Renderer9 : public Renderer ...@@ -221,7 +221,8 @@ class Renderer9 : public Renderer
void releaseDeviceResources(); void releaseDeviceResources();
HRESULT getDeviceStatusCode(); HRESULT getDeviceStatusCode();
HRESULT resetRemovedDevice(); bool isRemovedDeviceResettable() const;
bool resetRemovedDevice();
UINT mAdapter; UINT mAdapter;
D3DDEVTYPE mDeviceType; D3DDEVTYPE mDeviceType;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment