mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-12 13:08:50 +01:00
[d3d9] Reject Reset if there's any remaining DEFAULT resources
This commit is contained in:
parent
a1a91dd766
commit
52ac271acb
@ -20,6 +20,11 @@ namespace dxvk {
|
||||
m_dirtyRange = D3D9Range(0, m_desc.Size);
|
||||
}
|
||||
|
||||
D3D9CommonBuffer::~D3D9CommonBuffer() {
|
||||
if (m_desc.Pool == D3DPOOL_DEFAULT)
|
||||
m_parent->DecrementLosableCounter();
|
||||
}
|
||||
|
||||
|
||||
HRESULT D3D9CommonBuffer::Lock(
|
||||
UINT OffsetToLock,
|
||||
|
@ -78,6 +78,8 @@ namespace dxvk {
|
||||
D3D9DeviceEx* pDevice,
|
||||
const D3D9_BUFFER_DESC* pDesc);
|
||||
|
||||
~D3D9CommonBuffer();
|
||||
|
||||
HRESULT Lock(
|
||||
UINT OffsetToLock,
|
||||
UINT SizeToLock,
|
||||
|
@ -98,6 +98,9 @@ namespace dxvk {
|
||||
m_device->ChangeReportedMemory(m_size);
|
||||
|
||||
m_device->RemoveMappedTexture(this);
|
||||
|
||||
if (m_desc.IsLosable)
|
||||
m_device->DecrementLosableCounter();
|
||||
}
|
||||
|
||||
|
||||
|
@ -48,6 +48,7 @@ namespace dxvk {
|
||||
bool IsBackBuffer;
|
||||
bool IsAttachmentOnly;
|
||||
bool IsLockable;
|
||||
bool IsLosable;
|
||||
};
|
||||
|
||||
struct D3D9ColorView {
|
||||
|
@ -415,11 +415,42 @@ namespace dxvk {
|
||||
Logger::info("Device reset");
|
||||
m_deviceLostState = D3D9DeviceLostState::Ok;
|
||||
|
||||
HRESULT hr = ResetSwapChain(pPresentationParameters, nullptr);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
if (!IsExtended()) {
|
||||
// The internal references are always cleared, regardless of whether the Reset call succeeds.
|
||||
ResetState(pPresentationParameters);
|
||||
m_implicitSwapchain->DestroyBackBuffers();
|
||||
m_autoDepthStencil = nullptr;
|
||||
} else {
|
||||
// Extended devices only reset the bound render targets
|
||||
for (uint32_t i = 0; i < caps::MaxSimultaneousRenderTargets; i++) {
|
||||
SetRenderTargetInternal(i, nullptr);
|
||||
}
|
||||
SetDepthStencilSurface(nullptr);
|
||||
}
|
||||
|
||||
ResetState(pPresentationParameters);
|
||||
/*
|
||||
* Before calling the IDirect3DDevice9::Reset method for a device,
|
||||
* an application should release any explicit render targets,
|
||||
* depth stencil surfaces, additional swap chains, state blocks,
|
||||
* and D3DPOOL_DEFAULT resources associated with the device.
|
||||
*
|
||||
* We have to check after ResetState clears the references held by SetTexture, etc.
|
||||
* This matches what Windows D3D9 does.
|
||||
*/
|
||||
if (unlikely(m_losableResourceCounter.load() != 0 && !IsExtended())) {
|
||||
Logger::warn(str::format("Device reset failed because device still has alive losable resources: Device not reset. Remaining resources: ", m_losableResourceCounter.load()));
|
||||
m_deviceLostState = D3D9DeviceLostState::NotReset;
|
||||
return D3DERR_INVALIDCALL;
|
||||
}
|
||||
|
||||
HRESULT hr = ResetSwapChain(pPresentationParameters, nullptr);
|
||||
if (FAILED(hr)) {
|
||||
if (!IsExtended()) {
|
||||
Logger::warn("Device reset failed: Device not reset");
|
||||
m_deviceLostState = D3D9DeviceLostState::NotReset;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
Flush();
|
||||
SynchronizeCsThread(DxvkCsThread::SynchronizeAll);
|
||||
@ -516,6 +547,7 @@ namespace dxvk {
|
||||
desc.MultisampleQuality = 0;
|
||||
desc.IsBackBuffer = FALSE;
|
||||
desc.IsAttachmentOnly = FALSE;
|
||||
desc.IsLosable = Pool == D3DPOOL_DEFAULT;
|
||||
// Docs:
|
||||
// Textures placed in the D3DPOOL_DEFAULT pool cannot be locked
|
||||
// unless they are dynamic textures or they are private, FOURCC, driver formats.
|
||||
@ -542,6 +574,9 @@ namespace dxvk {
|
||||
m_initializer->InitTexture(texture->GetCommonTexture(), initialData);
|
||||
*ppTexture = texture.ref();
|
||||
|
||||
if (desc.IsLosable)
|
||||
m_losableResourceCounter++;
|
||||
|
||||
return D3D_OK;
|
||||
}
|
||||
catch (const DxvkError& e) {
|
||||
@ -583,6 +618,7 @@ namespace dxvk {
|
||||
desc.MultisampleQuality = 0;
|
||||
desc.IsBackBuffer = FALSE;
|
||||
desc.IsAttachmentOnly = FALSE;
|
||||
desc.IsLosable = Pool == D3DPOOL_DEFAULT;
|
||||
// Docs:
|
||||
// Textures placed in the D3DPOOL_DEFAULT pool cannot be locked
|
||||
// unless they are dynamic textures or they are private, FOURCC, driver formats.
|
||||
@ -597,6 +633,9 @@ namespace dxvk {
|
||||
const Com<D3D9Texture3D> texture = new D3D9Texture3D(this, &desc);
|
||||
m_initializer->InitTexture(texture->GetCommonTexture());
|
||||
*ppVolumeTexture = texture.ref();
|
||||
|
||||
if (desc.IsLosable)
|
||||
m_losableResourceCounter++;
|
||||
|
||||
return D3D_OK;
|
||||
}
|
||||
@ -637,6 +676,7 @@ namespace dxvk {
|
||||
desc.MultisampleQuality = 0;
|
||||
desc.IsBackBuffer = FALSE;
|
||||
desc.IsAttachmentOnly = FALSE;
|
||||
desc.IsLosable = Pool == D3DPOOL_DEFAULT;
|
||||
// Docs:
|
||||
// Textures placed in the D3DPOOL_DEFAULT pool cannot be locked
|
||||
// unless they are dynamic textures or they are private, FOURCC, driver formats.
|
||||
@ -651,6 +691,9 @@ namespace dxvk {
|
||||
const Com<D3D9TextureCube> texture = new D3D9TextureCube(this, &desc);
|
||||
m_initializer->InitTexture(texture->GetCommonTexture());
|
||||
*ppCubeTexture = texture.ref();
|
||||
|
||||
if (desc.IsLosable)
|
||||
m_losableResourceCounter++;
|
||||
|
||||
return D3D_OK;
|
||||
}
|
||||
@ -691,6 +734,9 @@ namespace dxvk {
|
||||
const Com<D3D9VertexBuffer> buffer = new D3D9VertexBuffer(this, &desc);
|
||||
m_initializer->InitBuffer(buffer->GetCommonBuffer());
|
||||
*ppVertexBuffer = buffer.ref();
|
||||
if (desc.Pool == D3DPOOL_DEFAULT)
|
||||
m_losableResourceCounter++;
|
||||
|
||||
return D3D_OK;
|
||||
}
|
||||
catch (const DxvkError & e) {
|
||||
@ -729,6 +775,9 @@ namespace dxvk {
|
||||
const Com<D3D9IndexBuffer> buffer = new D3D9IndexBuffer(this, &desc);
|
||||
m_initializer->InitBuffer(buffer->GetCommonBuffer());
|
||||
*ppIndexBuffer = buffer.ref();
|
||||
if (desc.Pool == D3DPOOL_DEFAULT)
|
||||
m_losableResourceCounter++;
|
||||
|
||||
return D3D_OK;
|
||||
}
|
||||
catch (const DxvkError & e) {
|
||||
@ -1311,14 +1360,22 @@ namespace dxvk {
|
||||
0);
|
||||
}
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetRenderTarget(
|
||||
DWORD RenderTargetIndex,
|
||||
IDirect3DSurface9* pRenderTarget) {
|
||||
D3D9DeviceLock lock = LockDevice();
|
||||
|
||||
if (unlikely(RenderTargetIndex >= caps::MaxSimultaneousRenderTargets
|
||||
|| (pRenderTarget == nullptr && RenderTargetIndex == 0)))
|
||||
if (unlikely((pRenderTarget == nullptr && RenderTargetIndex == 0)))
|
||||
return D3DERR_INVALIDCALL;
|
||||
|
||||
return SetRenderTargetInternal(RenderTargetIndex, pRenderTarget);
|
||||
}
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetRenderTargetInternal(
|
||||
DWORD RenderTargetIndex,
|
||||
IDirect3DSurface9* pRenderTarget) {
|
||||
if (unlikely(RenderTargetIndex >= caps::MaxSimultaneousRenderTargets))
|
||||
return D3DERR_INVALIDCALL;
|
||||
|
||||
D3D9Surface* rt = static_cast<D3D9Surface*>(pRenderTarget);
|
||||
@ -1330,21 +1387,28 @@ namespace dxvk {
|
||||
return D3DERR_INVALIDCALL;
|
||||
|
||||
if (RenderTargetIndex == 0) {
|
||||
auto rtSize = rt->GetSurfaceExtent();
|
||||
|
||||
D3DVIEWPORT9 viewport;
|
||||
viewport.X = 0;
|
||||
viewport.Y = 0;
|
||||
viewport.Width = rtSize.width;
|
||||
viewport.Height = rtSize.height;
|
||||
viewport.MinZ = 0.0f;
|
||||
viewport.MaxZ = 1.0f;
|
||||
|
||||
RECT scissorRect;
|
||||
scissorRect.left = 0;
|
||||
scissorRect.top = 0;
|
||||
scissorRect.right = rtSize.width;
|
||||
scissorRect.bottom = rtSize.height;
|
||||
|
||||
if (likely(rt != nullptr)) {
|
||||
auto rtSize = rt->GetSurfaceExtent();
|
||||
viewport.Width = rtSize.width;
|
||||
viewport.Height = rtSize.height;
|
||||
scissorRect.right = rtSize.width;
|
||||
scissorRect.bottom = rtSize.height;
|
||||
} else {
|
||||
viewport.Width = 0;
|
||||
viewport.Height = 0;
|
||||
scissorRect.right = 0;
|
||||
scissorRect.bottom = 0;
|
||||
}
|
||||
|
||||
if (m_state.viewport != viewport) {
|
||||
m_flags.set(D3D9DeviceFlag::DirtyFFViewport);
|
||||
@ -1389,13 +1453,18 @@ namespace dxvk {
|
||||
m_flags.set(D3D9DeviceFlag::DirtyBlendState);
|
||||
|
||||
if (RenderTargetIndex == 0) {
|
||||
bool validSampleMask = texInfo->Desc()->MultiSample > D3DMULTISAMPLE_NONMASKABLE;
|
||||
if (likely(texInfo != nullptr)) {
|
||||
bool validSampleMask = texInfo->Desc()->MultiSample > D3DMULTISAMPLE_NONMASKABLE;
|
||||
|
||||
if (validSampleMask != m_flags.test(D3D9DeviceFlag::ValidSampleMask)) {
|
||||
if (validSampleMask != m_flags.test(D3D9DeviceFlag::ValidSampleMask)) {
|
||||
m_flags.clr(D3D9DeviceFlag::ValidSampleMask);
|
||||
if (validSampleMask)
|
||||
m_flags.set(D3D9DeviceFlag::ValidSampleMask);
|
||||
|
||||
m_flags.set(D3D9DeviceFlag::DirtyMultiSampleState);
|
||||
}
|
||||
} else {
|
||||
m_flags.clr(D3D9DeviceFlag::ValidSampleMask);
|
||||
if (validSampleMask)
|
||||
m_flags.set(D3D9DeviceFlag::ValidSampleMask);
|
||||
|
||||
m_flags.set(D3D9DeviceFlag::DirtyMultiSampleState);
|
||||
}
|
||||
}
|
||||
@ -2254,6 +2323,8 @@ namespace dxvk {
|
||||
try {
|
||||
const Com<D3D9StateBlock> sb = new D3D9StateBlock(this, ConvertStateBlockType(Type));
|
||||
*ppSB = sb.ref();
|
||||
m_losableResourceCounter++;
|
||||
|
||||
return D3D_OK;
|
||||
}
|
||||
catch (const DxvkError & e) {
|
||||
@ -2284,6 +2355,7 @@ namespace dxvk {
|
||||
return D3DERR_INVALIDCALL;
|
||||
|
||||
*ppSB = m_recorder.ref();
|
||||
m_losableResourceCounter++;
|
||||
m_recorder = nullptr;
|
||||
|
||||
return D3D_OK;
|
||||
@ -3613,6 +3685,7 @@ namespace dxvk {
|
||||
desc.IsBackBuffer = FALSE;
|
||||
desc.IsAttachmentOnly = TRUE;
|
||||
desc.IsLockable = Lockable;
|
||||
desc.IsLosable = TRUE;
|
||||
|
||||
if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, &desc)))
|
||||
return D3DERR_INVALIDCALL;
|
||||
@ -3621,6 +3694,8 @@ namespace dxvk {
|
||||
const Com<D3D9Surface> surface = new D3D9Surface(this, &desc, nullptr, pSharedHandle);
|
||||
m_initializer->InitTexture(surface->GetCommonTexture());
|
||||
*ppSurface = surface.ref();
|
||||
m_losableResourceCounter++;
|
||||
|
||||
return D3D_OK;
|
||||
}
|
||||
catch (const DxvkError& e) {
|
||||
@ -3657,6 +3732,7 @@ namespace dxvk {
|
||||
desc.MultisampleQuality = 0;
|
||||
desc.IsBackBuffer = FALSE;
|
||||
desc.IsAttachmentOnly = Pool == D3DPOOL_DEFAULT;
|
||||
desc.IsLosable = Pool == D3DPOOL_DEFAULT;
|
||||
// Docs: Off-screen plain surfaces are always lockable, regardless of their pool types.
|
||||
desc.IsLockable = TRUE;
|
||||
|
||||
@ -3670,6 +3746,10 @@ namespace dxvk {
|
||||
const Com<D3D9Surface> surface = new D3D9Surface(this, &desc, nullptr, pSharedHandle);
|
||||
m_initializer->InitTexture(surface->GetCommonTexture());
|
||||
*ppSurface = surface.ref();
|
||||
|
||||
if (desc.IsLosable)
|
||||
m_losableResourceCounter++;
|
||||
|
||||
return D3D_OK;
|
||||
}
|
||||
catch (const DxvkError& e) {
|
||||
@ -3708,6 +3788,7 @@ namespace dxvk {
|
||||
desc.MultisampleQuality = MultisampleQuality;
|
||||
desc.IsBackBuffer = FALSE;
|
||||
desc.IsAttachmentOnly = TRUE;
|
||||
desc.IsLosable = TRUE;
|
||||
// Docs don't say anything, so just assume it's lockable.
|
||||
desc.IsLockable = TRUE;
|
||||
|
||||
@ -3718,6 +3799,8 @@ namespace dxvk {
|
||||
const Com<D3D9Surface> surface = new D3D9Surface(this, &desc, nullptr, pSharedHandle);
|
||||
m_initializer->InitTexture(surface->GetCommonTexture());
|
||||
*ppSurface = surface.ref();
|
||||
m_losableResourceCounter++;
|
||||
|
||||
return D3D_OK;
|
||||
}
|
||||
catch (const DxvkError& e) {
|
||||
@ -3779,6 +3862,7 @@ namespace dxvk {
|
||||
try {
|
||||
auto* swapchain = new D3D9SwapChainEx(this, pPresentationParameters, pFullscreenDisplayMode);
|
||||
*ppSwapChain = ref(swapchain);
|
||||
m_losableResourceCounter++;
|
||||
}
|
||||
catch (const DxvkError & e) {
|
||||
Logger::err(e.message());
|
||||
@ -7171,11 +7255,10 @@ namespace dxvk {
|
||||
|
||||
|
||||
void D3D9DeviceEx::ResetState(D3DPRESENT_PARAMETERS* pPresentationParameters) {
|
||||
if (!pPresentationParameters->EnableAutoDepthStencil)
|
||||
SetDepthStencilSurface(nullptr);
|
||||
SetDepthStencilSurface(nullptr);
|
||||
|
||||
for (uint32_t i = 1; i < caps::MaxSimultaneousRenderTargets; i++)
|
||||
SetRenderTarget(i, nullptr);
|
||||
for (uint32_t i = 0; i < caps::MaxSimultaneousRenderTargets; i++)
|
||||
SetRenderTargetInternal(i, nullptr);
|
||||
|
||||
auto& rs = m_state.renderStates;
|
||||
|
||||
@ -7358,8 +7441,9 @@ namespace dxvk {
|
||||
for (uint32_t i = 0; i < caps::MaxStreams; i++)
|
||||
m_state.streamFreq[i] = 1;
|
||||
|
||||
for (uint32_t i = 0; i < m_state.textures->size(); i++)
|
||||
for (uint32_t i = 0; i < m_state.textures->size(); i++) {
|
||||
SetStateTexture(i, nullptr);
|
||||
}
|
||||
|
||||
EmitCs([
|
||||
cSize = m_state.textures->size()
|
||||
@ -7465,6 +7549,7 @@ namespace dxvk {
|
||||
desc.MultisampleQuality = pPresentationParameters->MultiSampleQuality;
|
||||
desc.IsBackBuffer = FALSE;
|
||||
desc.IsAttachmentOnly = TRUE;
|
||||
desc.IsLosable = TRUE;
|
||||
// Docs: Also note that - unlike textures - swap chain back buffers, render targets [..] can be locked
|
||||
desc.IsLockable = TRUE;
|
||||
|
||||
@ -7474,6 +7559,7 @@ namespace dxvk {
|
||||
m_autoDepthStencil = new D3D9Surface(this, &desc, nullptr, nullptr);
|
||||
m_initializer->InitTexture(m_autoDepthStencil->GetCommonTexture());
|
||||
SetDepthStencilSurface(m_autoDepthStencil.ptr());
|
||||
m_losableResourceCounter++;
|
||||
}
|
||||
|
||||
SetRenderTarget(0, m_implicitSwapchain->GetBackBuffer(0));
|
||||
@ -7575,6 +7661,43 @@ namespace dxvk {
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// D3D9 Device Lost
|
||||
////////////////////////////////////
|
||||
|
||||
void D3D9DeviceEx::NotifyFullscreen(HWND window, bool fullscreen) {
|
||||
D3D9DeviceLock lock = LockDevice();
|
||||
|
||||
if (fullscreen) {
|
||||
if (unlikely(window != m_fullscreenWindow && m_fullscreenWindow != NULL)) {
|
||||
Logger::warn("Multiple fullscreen windows detected.");
|
||||
}
|
||||
m_fullscreenWindow = window;
|
||||
} else {
|
||||
if (unlikely(m_fullscreenWindow != window)) {
|
||||
Logger::warn("Window was not fullscreen in the first place.");
|
||||
} else {
|
||||
m_fullscreenWindow = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void D3D9DeviceEx::NotifyWindowActivated(HWND window, bool activated) {
|
||||
D3D9DeviceLock lock = LockDevice();
|
||||
|
||||
if (likely(!m_d3d9Options.deviceLossOnFocusLoss || IsExtended()))
|
||||
return;
|
||||
|
||||
if (activated && m_deviceLostState == D3D9DeviceLostState::Lost) {
|
||||
Logger::info("Device not reset");
|
||||
m_deviceLostState = D3D9DeviceLostState::NotReset;
|
||||
} else if (!activated && m_deviceLostState != D3D9DeviceLostState::Lost && m_fullscreenWindow == window) {
|
||||
Logger::info("Device lost");
|
||||
m_deviceLostState = D3D9DeviceLostState::Lost;
|
||||
m_fullscreenWindow = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// D3D9 Device Specialization State
|
||||
////////////////////////////////////
|
||||
|
@ -879,6 +879,10 @@ namespace dxvk {
|
||||
|
||||
void MarkTextureBindingDirty(IDirect3DBaseTexture9* texture);
|
||||
|
||||
HRESULT STDMETHODCALLTYPE SetRenderTargetInternal(
|
||||
DWORD RenderTargetIndex,
|
||||
IDirect3DSurface9* pRenderTarget);
|
||||
|
||||
D3D9DrawInfo GenerateDrawInfo(
|
||||
D3DPRIMITIVETYPE PrimitiveType,
|
||||
UINT PrimitiveCount,
|
||||
@ -961,41 +965,20 @@ namespace dxvk {
|
||||
void TouchMappedTexture(D3D9CommonTexture* pTexture);
|
||||
void RemoveMappedTexture(D3D9CommonTexture* pTexture);
|
||||
|
||||
// Device Lost
|
||||
bool IsDeviceLost() const {
|
||||
return m_deviceLostState != D3D9DeviceLostState::Ok;
|
||||
}
|
||||
|
||||
void NotifyFullscreen(HWND window, bool fullscreen) {
|
||||
D3D9DeviceLock lock = LockDevice();
|
||||
void NotifyFullscreen(HWND window, bool fullscreen);
|
||||
void NotifyWindowActivated(HWND window, bool activated);
|
||||
|
||||
if (fullscreen) {
|
||||
if (unlikely(window != m_fullscreenWindow && m_fullscreenWindow != NULL)) {
|
||||
Logger::warn("Multiple fullscreen windows detected.");
|
||||
}
|
||||
m_fullscreenWindow = window;
|
||||
} else {
|
||||
if (unlikely(m_fullscreenWindow != window)) {
|
||||
Logger::warn("Window was not fullscreen in the first place.");
|
||||
} else {
|
||||
m_fullscreenWindow = 0;
|
||||
}
|
||||
}
|
||||
void IncrementLosableCounter() {
|
||||
m_losableResourceCounter++;
|
||||
}
|
||||
|
||||
void NotifyWindowActivated(HWND window, bool activated) {
|
||||
D3D9DeviceLock lock = LockDevice();
|
||||
|
||||
if (likely(!m_d3d9Options.deviceLost || IsExtended()))
|
||||
return;
|
||||
|
||||
if (activated && m_deviceLostState == D3D9DeviceLostState::Lost) {
|
||||
Logger::info("Device not reset");
|
||||
m_deviceLostState = D3D9DeviceLostState::NotReset;
|
||||
} else if (!activated && m_deviceLostState != D3D9DeviceLostState::Lost && m_fullscreenWindow == window) {
|
||||
Logger::info("Device lost");
|
||||
m_deviceLostState = D3D9DeviceLostState::Lost;
|
||||
m_fullscreenWindow = NULL;
|
||||
}
|
||||
void DecrementLosableCounter() {
|
||||
m_losableResourceCounter--;
|
||||
}
|
||||
|
||||
bool CanOnlySWVP() const {
|
||||
@ -1369,6 +1352,7 @@ namespace dxvk {
|
||||
|
||||
D3D9DeviceLostState m_deviceLostState = D3D9DeviceLostState::Ok;
|
||||
HWND m_fullscreenWindow = NULL;
|
||||
std::atomic<uint32_t> m_losableResourceCounter = { 0 };
|
||||
|
||||
#ifdef D3D9_ALLOW_UNMAPPING
|
||||
lru_list<D3D9CommonTexture*> m_mappedTextures;
|
||||
|
@ -70,8 +70,8 @@ namespace dxvk {
|
||||
this->deviceLocalConstantBuffers = config.getOption<bool> ("d3d9.deviceLocalConstantBuffers", false);
|
||||
this->allowDirectBufferMapping = config.getOption<bool> ("d3d9.allowDirectBufferMapping", true);
|
||||
this->seamlessCubes = config.getOption<bool> ("d3d9.seamlessCubes", false);
|
||||
this->textureMemory = config.getOption<int32_t> ("d3d9.textureMemory", 100) << 20;
|
||||
this->deviceLost = config.getOption<bool> ("d3d9.deviceLost", false);
|
||||
this->textureMemory = config.getOption<int32_t> ("d3d9.textureMemory", 100) << 20;
|
||||
this->deviceLossOnFocusLoss = config.getOption<bool> ("d3d9.deviceLossOnFocusLoss", false);
|
||||
|
||||
std::string floatEmulation = Config::toLower(config.getOption<std::string>("d3d9.floatEmulation", "auto"));
|
||||
if (floatEmulation == "strict") {
|
||||
|
@ -143,7 +143,7 @@ namespace dxvk {
|
||||
std::string shaderDumpPath;
|
||||
|
||||
/// Enable emulation of device loss when a fullscreen app loses focus
|
||||
bool deviceLost;
|
||||
bool deviceLossOnFocusLoss;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -17,6 +17,9 @@ namespace dxvk {
|
||||
CaptureType(Type);
|
||||
}
|
||||
|
||||
D3D9StateBlock::~D3D9StateBlock() {
|
||||
m_parent->DecrementLosableCounter();
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE D3D9StateBlock::QueryInterface(
|
||||
REFIID riid,
|
||||
|
@ -89,6 +89,8 @@ namespace dxvk {
|
||||
|
||||
D3D9StateBlock(D3D9DeviceEx* pDevice, D3D9StateBlockType Type);
|
||||
|
||||
~D3D9StateBlock();
|
||||
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(
|
||||
REFIID riid,
|
||||
void** ppvObject) final;
|
||||
|
@ -71,6 +71,8 @@ namespace dxvk {
|
||||
|
||||
m_device->waitForSubmission(&m_presentStatus);
|
||||
m_device->waitForIdle();
|
||||
|
||||
m_parent->DecrementLosableCounter();
|
||||
}
|
||||
|
||||
|
||||
@ -436,6 +438,13 @@ namespace dxvk {
|
||||
return D3DERR_INVALIDCALL;
|
||||
}
|
||||
|
||||
if (m_backBuffers.empty()) {
|
||||
// The backbuffers were destroyed and not recreated.
|
||||
// This can happen when a call to Reset fails.
|
||||
*ppBackBuffer = nullptr;
|
||||
return D3D_OK;
|
||||
}
|
||||
|
||||
*ppBackBuffer = ref(m_backBuffers[iBackBuffer].ptr());
|
||||
return D3D_OK;
|
||||
}
|
||||
@ -977,6 +986,7 @@ namespace dxvk {
|
||||
desc.Discard = FALSE;
|
||||
desc.IsBackBuffer = TRUE;
|
||||
desc.IsAttachmentOnly = FALSE;
|
||||
desc.IsLosable = TRUE;
|
||||
// Docs: Also note that - unlike textures - swap chain back buffers, render targets [..] can be locked
|
||||
desc.IsLockable = TRUE;
|
||||
|
||||
@ -984,6 +994,7 @@ namespace dxvk {
|
||||
D3D9Surface* surface;
|
||||
try {
|
||||
surface = new D3D9Surface(m_parent, &desc, this, nullptr);
|
||||
m_parent->IncrementLosableCounter();
|
||||
} catch (const DxvkError& e) {
|
||||
DestroyBackBuffers();
|
||||
Logger::err(e.message());
|
||||
|
@ -120,6 +120,8 @@ namespace dxvk {
|
||||
|
||||
bool HasFormatsUnlocked() const { return m_unlockAdditionalFormats; }
|
||||
|
||||
void DestroyBackBuffers();
|
||||
|
||||
private:
|
||||
|
||||
enum BindingIds : uint32_t {
|
||||
@ -189,8 +191,6 @@ namespace dxvk {
|
||||
|
||||
void CreateRenderTargetViews();
|
||||
|
||||
void DestroyBackBuffers();
|
||||
|
||||
HRESULT CreateBackBuffers(
|
||||
uint32_t NumBackBuffers);
|
||||
|
||||
|
@ -500,7 +500,7 @@ namespace dxvk {
|
||||
{ "d3d9.customVendorId", "1002" },
|
||||
{ "dxgi.emulateUMA", "True" },
|
||||
{ "d3d9.supportDFFormats", "False" },
|
||||
{ "d3d9.deviceLost", "True" },
|
||||
{ "d3d9.deviceLostOnFocusLoss", "True" },
|
||||
}} },
|
||||
/* Battlefield 2 (bad z-pass) */
|
||||
{ R"(\\BF2\.exe$)", {{
|
||||
@ -754,7 +754,7 @@ namespace dxvk {
|
||||
/* DC Universe Online *
|
||||
* Freezes after alt tabbing */
|
||||
{ R"(\\DCGAME\.EXE$)", {{
|
||||
{ "d3d9.deviceLost", "True" },
|
||||
{ "d3d9.deviceLostOnFocusLoss", "True" },
|
||||
}} },
|
||||
/* Halo Online *
|
||||
* Black textures */
|
||||
|
Loading…
Reference in New Issue
Block a user