mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-12 13:08:50 +01:00
[d3d9] Handle swapchain OOM and other errors more gracefully
Supercedes: #2964
This commit is contained in:
parent
20356148af
commit
f140d2de0d
@ -7363,8 +7363,9 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_implicitSwapchain != nullptr) {
|
if (m_implicitSwapchain != nullptr) {
|
||||||
if (FAILED(m_implicitSwapchain->Reset(pPresentationParameters, pFullscreenDisplayMode)))
|
HRESULT hr = m_implicitSwapchain->Reset(pPresentationParameters, pFullscreenDisplayMode);
|
||||||
return D3DERR_INVALIDCALL;
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_implicitSwapchain = new D3D9SwapChainEx(this, pPresentationParameters, pFullscreenDisplayMode);
|
m_implicitSwapchain = new D3D9SwapChainEx(this, pPresentationParameters, pFullscreenDisplayMode);
|
||||||
|
@ -43,7 +43,9 @@ namespace dxvk {
|
|||||||
RecreateSwapChain(false);
|
RecreateSwapChain(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateBackBuffers(m_presentParams.BackBufferCount);
|
if (FAILED(CreateBackBuffers(m_presentParams.BackBufferCount)))
|
||||||
|
throw DxvkError("D3D9: Failed to create swapchain backbuffers");
|
||||||
|
|
||||||
CreateBlitter();
|
CreateBlitter();
|
||||||
CreateHud();
|
CreateHud();
|
||||||
|
|
||||||
@ -101,6 +103,14 @@ namespace dxvk {
|
|||||||
DWORD dwFlags) {
|
DWORD dwFlags) {
|
||||||
D3D9DeviceLock lock = m_parent->LockDevice();
|
D3D9DeviceLock lock = m_parent->LockDevice();
|
||||||
|
|
||||||
|
// If we have no backbuffers, error out.
|
||||||
|
// This handles the case where a ::Reset failed due to OOM
|
||||||
|
// or whatever.
|
||||||
|
// I am not sure what the actual HRESULT returned here is
|
||||||
|
// or should be, but it is better than crashing... probably!
|
||||||
|
if (m_backBuffers.empty())
|
||||||
|
return D3D_OK;
|
||||||
|
|
||||||
uint32_t presentInterval = m_presentParams.PresentationInterval;
|
uint32_t presentInterval = m_presentParams.PresentationInterval;
|
||||||
|
|
||||||
// This is not true directly in d3d9 to to timing differences that don't matter for us.
|
// This is not true directly in d3d9 to to timing differences that don't matter for us.
|
||||||
@ -515,6 +525,8 @@ namespace dxvk {
|
|||||||
D3DDISPLAYMODEEX* pFullscreenDisplayMode) {
|
D3DDISPLAYMODEEX* pFullscreenDisplayMode) {
|
||||||
D3D9DeviceLock lock = m_parent->LockDevice();
|
D3D9DeviceLock lock = m_parent->LockDevice();
|
||||||
|
|
||||||
|
HRESULT hr = D3D_OK;
|
||||||
|
|
||||||
this->SynchronizePresent();
|
this->SynchronizePresent();
|
||||||
this->NormalizePresentParameters(pPresentParams);
|
this->NormalizePresentParameters(pPresentParams);
|
||||||
|
|
||||||
@ -529,15 +541,17 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (changeFullscreen) {
|
if (changeFullscreen) {
|
||||||
if (FAILED(this->EnterFullscreenMode(pPresentParams, pFullscreenDisplayMode)))
|
hr = this->EnterFullscreenMode(pPresentParams, pFullscreenDisplayMode);
|
||||||
return D3DERR_INVALIDCALL;
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
D3D9WindowMessageFilter filter(m_window);
|
D3D9WindowMessageFilter filter(m_window);
|
||||||
|
|
||||||
if (!changeFullscreen) {
|
if (!changeFullscreen) {
|
||||||
if (FAILED(ChangeDisplayMode(pPresentParams, pFullscreenDisplayMode)))
|
hr = ChangeDisplayMode(pPresentParams, pFullscreenDisplayMode);
|
||||||
return D3DERR_INVALIDCALL;
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
wsi::updateFullscreenWindow(m_monitor, m_window, true);
|
wsi::updateFullscreenWindow(m_monitor, m_window, true);
|
||||||
}
|
}
|
||||||
@ -548,7 +562,9 @@ namespace dxvk {
|
|||||||
if (changeFullscreen)
|
if (changeFullscreen)
|
||||||
SetGammaRamp(0, &m_ramp);
|
SetGammaRamp(0, &m_ramp);
|
||||||
|
|
||||||
CreateBackBuffers(m_presentParams.BackBufferCount);
|
hr = CreateBackBuffers(m_presentParams.BackBufferCount);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
}
|
}
|
||||||
@ -921,13 +937,15 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void D3D9SwapChainEx::CreateBackBuffers(uint32_t NumBackBuffers) {
|
HRESULT D3D9SwapChainEx::CreateBackBuffers(uint32_t NumBackBuffers) {
|
||||||
// Explicitly destroy current swap image before
|
// Explicitly destroy current swap image before
|
||||||
// creating a new one to free up resources
|
// creating a new one to free up resources
|
||||||
DestroyBackBuffers();
|
DestroyBackBuffers();
|
||||||
|
|
||||||
int NumFrontBuffer = m_parent->GetOptions()->noExplicitFrontBuffer ? 0 : 1;
|
int NumFrontBuffer = m_parent->GetOptions()->noExplicitFrontBuffer ? 0 : 1;
|
||||||
m_backBuffers.resize(NumBackBuffers + NumFrontBuffer);
|
const uint32_t NumBuffers = NumBackBuffers + NumFrontBuffer;
|
||||||
|
|
||||||
|
m_backBuffers.reserve(NumBuffers);
|
||||||
|
|
||||||
// Create new back buffer
|
// Create new back buffer
|
||||||
D3D9_COMMON_TEXTURE_DESC desc;
|
D3D9_COMMON_TEXTURE_DESC desc;
|
||||||
@ -947,8 +965,18 @@ namespace dxvk {
|
|||||||
// Docs: Also note that - unlike textures - swap chain back buffers, render targets [..] can be locked
|
// Docs: Also note that - unlike textures - swap chain back buffers, render targets [..] can be locked
|
||||||
desc.IsLockable = TRUE;
|
desc.IsLockable = TRUE;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < m_backBuffers.size(); i++)
|
for (uint32_t i = 0; i < NumBuffers; i++) {
|
||||||
m_backBuffers[i] = new D3D9Surface(m_parent, &desc, this, nullptr);
|
D3D9Surface* surface;
|
||||||
|
try {
|
||||||
|
surface = new D3D9Surface(m_parent, &desc, this, nullptr);
|
||||||
|
} catch (const DxvkError& e) {
|
||||||
|
DestroyBackBuffers();
|
||||||
|
Logger::err(e.message());
|
||||||
|
return D3DERR_OUTOFVIDEOMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_backBuffers.emplace_back(surface);
|
||||||
|
}
|
||||||
|
|
||||||
auto swapImage = m_backBuffers[0]->GetCommonTexture()->GetImage();
|
auto swapImage = m_backBuffers[0]->GetCommonTexture()->GetImage();
|
||||||
|
|
||||||
@ -973,6 +1001,8 @@ namespace dxvk {
|
|||||||
m_device->submitCommandList(
|
m_device->submitCommandList(
|
||||||
m_context->endRecording(),
|
m_context->endRecording(),
|
||||||
nullptr);
|
nullptr);
|
||||||
|
|
||||||
|
return D3D_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
void DestroyBackBuffers();
|
void DestroyBackBuffers();
|
||||||
|
|
||||||
void CreateBackBuffers(
|
HRESULT CreateBackBuffers(
|
||||||
uint32_t NumBackBuffers);
|
uint32_t NumBackBuffers);
|
||||||
|
|
||||||
void CreateBlitter();
|
void CreateBlitter();
|
||||||
|
Loading…
Reference in New Issue
Block a user