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);
|
m_dirtyRange = D3D9Range(0, m_desc.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
D3D9CommonBuffer::~D3D9CommonBuffer() {
|
||||||
|
if (m_desc.Pool == D3DPOOL_DEFAULT)
|
||||||
|
m_parent->DecrementLosableCounter();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
HRESULT D3D9CommonBuffer::Lock(
|
HRESULT D3D9CommonBuffer::Lock(
|
||||||
UINT OffsetToLock,
|
UINT OffsetToLock,
|
||||||
|
@ -78,6 +78,8 @@ namespace dxvk {
|
|||||||
D3D9DeviceEx* pDevice,
|
D3D9DeviceEx* pDevice,
|
||||||
const D3D9_BUFFER_DESC* pDesc);
|
const D3D9_BUFFER_DESC* pDesc);
|
||||||
|
|
||||||
|
~D3D9CommonBuffer();
|
||||||
|
|
||||||
HRESULT Lock(
|
HRESULT Lock(
|
||||||
UINT OffsetToLock,
|
UINT OffsetToLock,
|
||||||
UINT SizeToLock,
|
UINT SizeToLock,
|
||||||
|
@ -98,6 +98,9 @@ namespace dxvk {
|
|||||||
m_device->ChangeReportedMemory(m_size);
|
m_device->ChangeReportedMemory(m_size);
|
||||||
|
|
||||||
m_device->RemoveMappedTexture(this);
|
m_device->RemoveMappedTexture(this);
|
||||||
|
|
||||||
|
if (m_desc.IsLosable)
|
||||||
|
m_device->DecrementLosableCounter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,6 +48,7 @@ namespace dxvk {
|
|||||||
bool IsBackBuffer;
|
bool IsBackBuffer;
|
||||||
bool IsAttachmentOnly;
|
bool IsAttachmentOnly;
|
||||||
bool IsLockable;
|
bool IsLockable;
|
||||||
|
bool IsLosable;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct D3D9ColorView {
|
struct D3D9ColorView {
|
||||||
|
@ -415,11 +415,42 @@ namespace dxvk {
|
|||||||
Logger::info("Device reset");
|
Logger::info("Device reset");
|
||||||
m_deviceLostState = D3D9DeviceLostState::Ok;
|
m_deviceLostState = D3D9DeviceLostState::Ok;
|
||||||
|
|
||||||
HRESULT hr = ResetSwapChain(pPresentationParameters, nullptr);
|
if (!IsExtended()) {
|
||||||
if (FAILED(hr))
|
// The internal references are always cleared, regardless of whether the Reset call succeeds.
|
||||||
return hr;
|
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();
|
Flush();
|
||||||
SynchronizeCsThread(DxvkCsThread::SynchronizeAll);
|
SynchronizeCsThread(DxvkCsThread::SynchronizeAll);
|
||||||
@ -516,6 +547,7 @@ namespace dxvk {
|
|||||||
desc.MultisampleQuality = 0;
|
desc.MultisampleQuality = 0;
|
||||||
desc.IsBackBuffer = FALSE;
|
desc.IsBackBuffer = FALSE;
|
||||||
desc.IsAttachmentOnly = FALSE;
|
desc.IsAttachmentOnly = FALSE;
|
||||||
|
desc.IsLosable = Pool == D3DPOOL_DEFAULT;
|
||||||
// Docs:
|
// Docs:
|
||||||
// Textures placed in the D3DPOOL_DEFAULT pool cannot be locked
|
// Textures placed in the D3DPOOL_DEFAULT pool cannot be locked
|
||||||
// unless they are dynamic textures or they are private, FOURCC, driver formats.
|
// unless they are dynamic textures or they are private, FOURCC, driver formats.
|
||||||
@ -542,6 +574,9 @@ namespace dxvk {
|
|||||||
m_initializer->InitTexture(texture->GetCommonTexture(), initialData);
|
m_initializer->InitTexture(texture->GetCommonTexture(), initialData);
|
||||||
*ppTexture = texture.ref();
|
*ppTexture = texture.ref();
|
||||||
|
|
||||||
|
if (desc.IsLosable)
|
||||||
|
m_losableResourceCounter++;
|
||||||
|
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
}
|
}
|
||||||
catch (const DxvkError& e) {
|
catch (const DxvkError& e) {
|
||||||
@ -583,6 +618,7 @@ namespace dxvk {
|
|||||||
desc.MultisampleQuality = 0;
|
desc.MultisampleQuality = 0;
|
||||||
desc.IsBackBuffer = FALSE;
|
desc.IsBackBuffer = FALSE;
|
||||||
desc.IsAttachmentOnly = FALSE;
|
desc.IsAttachmentOnly = FALSE;
|
||||||
|
desc.IsLosable = Pool == D3DPOOL_DEFAULT;
|
||||||
// Docs:
|
// Docs:
|
||||||
// Textures placed in the D3DPOOL_DEFAULT pool cannot be locked
|
// Textures placed in the D3DPOOL_DEFAULT pool cannot be locked
|
||||||
// unless they are dynamic textures or they are private, FOURCC, driver formats.
|
// 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);
|
const Com<D3D9Texture3D> texture = new D3D9Texture3D(this, &desc);
|
||||||
m_initializer->InitTexture(texture->GetCommonTexture());
|
m_initializer->InitTexture(texture->GetCommonTexture());
|
||||||
*ppVolumeTexture = texture.ref();
|
*ppVolumeTexture = texture.ref();
|
||||||
|
|
||||||
|
if (desc.IsLosable)
|
||||||
|
m_losableResourceCounter++;
|
||||||
|
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
}
|
}
|
||||||
@ -637,6 +676,7 @@ namespace dxvk {
|
|||||||
desc.MultisampleQuality = 0;
|
desc.MultisampleQuality = 0;
|
||||||
desc.IsBackBuffer = FALSE;
|
desc.IsBackBuffer = FALSE;
|
||||||
desc.IsAttachmentOnly = FALSE;
|
desc.IsAttachmentOnly = FALSE;
|
||||||
|
desc.IsLosable = Pool == D3DPOOL_DEFAULT;
|
||||||
// Docs:
|
// Docs:
|
||||||
// Textures placed in the D3DPOOL_DEFAULT pool cannot be locked
|
// Textures placed in the D3DPOOL_DEFAULT pool cannot be locked
|
||||||
// unless they are dynamic textures or they are private, FOURCC, driver formats.
|
// 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);
|
const Com<D3D9TextureCube> texture = new D3D9TextureCube(this, &desc);
|
||||||
m_initializer->InitTexture(texture->GetCommonTexture());
|
m_initializer->InitTexture(texture->GetCommonTexture());
|
||||||
*ppCubeTexture = texture.ref();
|
*ppCubeTexture = texture.ref();
|
||||||
|
|
||||||
|
if (desc.IsLosable)
|
||||||
|
m_losableResourceCounter++;
|
||||||
|
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
}
|
}
|
||||||
@ -691,6 +734,9 @@ namespace dxvk {
|
|||||||
const Com<D3D9VertexBuffer> buffer = new D3D9VertexBuffer(this, &desc);
|
const Com<D3D9VertexBuffer> buffer = new D3D9VertexBuffer(this, &desc);
|
||||||
m_initializer->InitBuffer(buffer->GetCommonBuffer());
|
m_initializer->InitBuffer(buffer->GetCommonBuffer());
|
||||||
*ppVertexBuffer = buffer.ref();
|
*ppVertexBuffer = buffer.ref();
|
||||||
|
if (desc.Pool == D3DPOOL_DEFAULT)
|
||||||
|
m_losableResourceCounter++;
|
||||||
|
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
}
|
}
|
||||||
catch (const DxvkError & e) {
|
catch (const DxvkError & e) {
|
||||||
@ -729,6 +775,9 @@ namespace dxvk {
|
|||||||
const Com<D3D9IndexBuffer> buffer = new D3D9IndexBuffer(this, &desc);
|
const Com<D3D9IndexBuffer> buffer = new D3D9IndexBuffer(this, &desc);
|
||||||
m_initializer->InitBuffer(buffer->GetCommonBuffer());
|
m_initializer->InitBuffer(buffer->GetCommonBuffer());
|
||||||
*ppIndexBuffer = buffer.ref();
|
*ppIndexBuffer = buffer.ref();
|
||||||
|
if (desc.Pool == D3DPOOL_DEFAULT)
|
||||||
|
m_losableResourceCounter++;
|
||||||
|
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
}
|
}
|
||||||
catch (const DxvkError & e) {
|
catch (const DxvkError & e) {
|
||||||
@ -1311,14 +1360,22 @@ namespace dxvk {
|
|||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetRenderTarget(
|
HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetRenderTarget(
|
||||||
DWORD RenderTargetIndex,
|
DWORD RenderTargetIndex,
|
||||||
IDirect3DSurface9* pRenderTarget) {
|
IDirect3DSurface9* pRenderTarget) {
|
||||||
D3D9DeviceLock lock = LockDevice();
|
D3D9DeviceLock lock = LockDevice();
|
||||||
|
|
||||||
if (unlikely(RenderTargetIndex >= caps::MaxSimultaneousRenderTargets
|
if (unlikely((pRenderTarget == nullptr && RenderTargetIndex == 0)))
|
||||||
|| (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;
|
return D3DERR_INVALIDCALL;
|
||||||
|
|
||||||
D3D9Surface* rt = static_cast<D3D9Surface*>(pRenderTarget);
|
D3D9Surface* rt = static_cast<D3D9Surface*>(pRenderTarget);
|
||||||
@ -1330,21 +1387,28 @@ namespace dxvk {
|
|||||||
return D3DERR_INVALIDCALL;
|
return D3DERR_INVALIDCALL;
|
||||||
|
|
||||||
if (RenderTargetIndex == 0) {
|
if (RenderTargetIndex == 0) {
|
||||||
auto rtSize = rt->GetSurfaceExtent();
|
|
||||||
|
|
||||||
D3DVIEWPORT9 viewport;
|
D3DVIEWPORT9 viewport;
|
||||||
viewport.X = 0;
|
viewport.X = 0;
|
||||||
viewport.Y = 0;
|
viewport.Y = 0;
|
||||||
viewport.Width = rtSize.width;
|
|
||||||
viewport.Height = rtSize.height;
|
|
||||||
viewport.MinZ = 0.0f;
|
viewport.MinZ = 0.0f;
|
||||||
viewport.MaxZ = 1.0f;
|
viewport.MaxZ = 1.0f;
|
||||||
|
|
||||||
RECT scissorRect;
|
RECT scissorRect;
|
||||||
scissorRect.left = 0;
|
scissorRect.left = 0;
|
||||||
scissorRect.top = 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) {
|
if (m_state.viewport != viewport) {
|
||||||
m_flags.set(D3D9DeviceFlag::DirtyFFViewport);
|
m_flags.set(D3D9DeviceFlag::DirtyFFViewport);
|
||||||
@ -1389,13 +1453,18 @@ namespace dxvk {
|
|||||||
m_flags.set(D3D9DeviceFlag::DirtyBlendState);
|
m_flags.set(D3D9DeviceFlag::DirtyBlendState);
|
||||||
|
|
||||||
if (RenderTargetIndex == 0) {
|
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);
|
m_flags.clr(D3D9DeviceFlag::ValidSampleMask);
|
||||||
if (validSampleMask)
|
|
||||||
m_flags.set(D3D9DeviceFlag::ValidSampleMask);
|
|
||||||
|
|
||||||
m_flags.set(D3D9DeviceFlag::DirtyMultiSampleState);
|
m_flags.set(D3D9DeviceFlag::DirtyMultiSampleState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2254,6 +2323,8 @@ namespace dxvk {
|
|||||||
try {
|
try {
|
||||||
const Com<D3D9StateBlock> sb = new D3D9StateBlock(this, ConvertStateBlockType(Type));
|
const Com<D3D9StateBlock> sb = new D3D9StateBlock(this, ConvertStateBlockType(Type));
|
||||||
*ppSB = sb.ref();
|
*ppSB = sb.ref();
|
||||||
|
m_losableResourceCounter++;
|
||||||
|
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
}
|
}
|
||||||
catch (const DxvkError & e) {
|
catch (const DxvkError & e) {
|
||||||
@ -2284,6 +2355,7 @@ namespace dxvk {
|
|||||||
return D3DERR_INVALIDCALL;
|
return D3DERR_INVALIDCALL;
|
||||||
|
|
||||||
*ppSB = m_recorder.ref();
|
*ppSB = m_recorder.ref();
|
||||||
|
m_losableResourceCounter++;
|
||||||
m_recorder = nullptr;
|
m_recorder = nullptr;
|
||||||
|
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
@ -3613,6 +3685,7 @@ namespace dxvk {
|
|||||||
desc.IsBackBuffer = FALSE;
|
desc.IsBackBuffer = FALSE;
|
||||||
desc.IsAttachmentOnly = TRUE;
|
desc.IsAttachmentOnly = TRUE;
|
||||||
desc.IsLockable = Lockable;
|
desc.IsLockable = Lockable;
|
||||||
|
desc.IsLosable = TRUE;
|
||||||
|
|
||||||
if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, &desc)))
|
if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, &desc)))
|
||||||
return D3DERR_INVALIDCALL;
|
return D3DERR_INVALIDCALL;
|
||||||
@ -3621,6 +3694,8 @@ namespace dxvk {
|
|||||||
const Com<D3D9Surface> surface = new D3D9Surface(this, &desc, nullptr, pSharedHandle);
|
const Com<D3D9Surface> surface = new D3D9Surface(this, &desc, nullptr, pSharedHandle);
|
||||||
m_initializer->InitTexture(surface->GetCommonTexture());
|
m_initializer->InitTexture(surface->GetCommonTexture());
|
||||||
*ppSurface = surface.ref();
|
*ppSurface = surface.ref();
|
||||||
|
m_losableResourceCounter++;
|
||||||
|
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
}
|
}
|
||||||
catch (const DxvkError& e) {
|
catch (const DxvkError& e) {
|
||||||
@ -3657,6 +3732,7 @@ namespace dxvk {
|
|||||||
desc.MultisampleQuality = 0;
|
desc.MultisampleQuality = 0;
|
||||||
desc.IsBackBuffer = FALSE;
|
desc.IsBackBuffer = FALSE;
|
||||||
desc.IsAttachmentOnly = Pool == D3DPOOL_DEFAULT;
|
desc.IsAttachmentOnly = Pool == D3DPOOL_DEFAULT;
|
||||||
|
desc.IsLosable = Pool == D3DPOOL_DEFAULT;
|
||||||
// Docs: Off-screen plain surfaces are always lockable, regardless of their pool types.
|
// Docs: Off-screen plain surfaces are always lockable, regardless of their pool types.
|
||||||
desc.IsLockable = TRUE;
|
desc.IsLockable = TRUE;
|
||||||
|
|
||||||
@ -3670,6 +3746,10 @@ namespace dxvk {
|
|||||||
const Com<D3D9Surface> surface = new D3D9Surface(this, &desc, nullptr, pSharedHandle);
|
const Com<D3D9Surface> surface = new D3D9Surface(this, &desc, nullptr, pSharedHandle);
|
||||||
m_initializer->InitTexture(surface->GetCommonTexture());
|
m_initializer->InitTexture(surface->GetCommonTexture());
|
||||||
*ppSurface = surface.ref();
|
*ppSurface = surface.ref();
|
||||||
|
|
||||||
|
if (desc.IsLosable)
|
||||||
|
m_losableResourceCounter++;
|
||||||
|
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
}
|
}
|
||||||
catch (const DxvkError& e) {
|
catch (const DxvkError& e) {
|
||||||
@ -3708,6 +3788,7 @@ namespace dxvk {
|
|||||||
desc.MultisampleQuality = MultisampleQuality;
|
desc.MultisampleQuality = MultisampleQuality;
|
||||||
desc.IsBackBuffer = FALSE;
|
desc.IsBackBuffer = FALSE;
|
||||||
desc.IsAttachmentOnly = TRUE;
|
desc.IsAttachmentOnly = TRUE;
|
||||||
|
desc.IsLosable = TRUE;
|
||||||
// Docs don't say anything, so just assume it's lockable.
|
// Docs don't say anything, so just assume it's lockable.
|
||||||
desc.IsLockable = TRUE;
|
desc.IsLockable = TRUE;
|
||||||
|
|
||||||
@ -3718,6 +3799,8 @@ namespace dxvk {
|
|||||||
const Com<D3D9Surface> surface = new D3D9Surface(this, &desc, nullptr, pSharedHandle);
|
const Com<D3D9Surface> surface = new D3D9Surface(this, &desc, nullptr, pSharedHandle);
|
||||||
m_initializer->InitTexture(surface->GetCommonTexture());
|
m_initializer->InitTexture(surface->GetCommonTexture());
|
||||||
*ppSurface = surface.ref();
|
*ppSurface = surface.ref();
|
||||||
|
m_losableResourceCounter++;
|
||||||
|
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
}
|
}
|
||||||
catch (const DxvkError& e) {
|
catch (const DxvkError& e) {
|
||||||
@ -3779,6 +3862,7 @@ namespace dxvk {
|
|||||||
try {
|
try {
|
||||||
auto* swapchain = new D3D9SwapChainEx(this, pPresentationParameters, pFullscreenDisplayMode);
|
auto* swapchain = new D3D9SwapChainEx(this, pPresentationParameters, pFullscreenDisplayMode);
|
||||||
*ppSwapChain = ref(swapchain);
|
*ppSwapChain = ref(swapchain);
|
||||||
|
m_losableResourceCounter++;
|
||||||
}
|
}
|
||||||
catch (const DxvkError & e) {
|
catch (const DxvkError & e) {
|
||||||
Logger::err(e.message());
|
Logger::err(e.message());
|
||||||
@ -7171,11 +7255,10 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
void D3D9DeviceEx::ResetState(D3DPRESENT_PARAMETERS* pPresentationParameters) {
|
void D3D9DeviceEx::ResetState(D3DPRESENT_PARAMETERS* pPresentationParameters) {
|
||||||
if (!pPresentationParameters->EnableAutoDepthStencil)
|
SetDepthStencilSurface(nullptr);
|
||||||
SetDepthStencilSurface(nullptr);
|
|
||||||
|
|
||||||
for (uint32_t i = 1; i < caps::MaxSimultaneousRenderTargets; i++)
|
for (uint32_t i = 0; i < caps::MaxSimultaneousRenderTargets; i++)
|
||||||
SetRenderTarget(i, nullptr);
|
SetRenderTargetInternal(i, nullptr);
|
||||||
|
|
||||||
auto& rs = m_state.renderStates;
|
auto& rs = m_state.renderStates;
|
||||||
|
|
||||||
@ -7358,8 +7441,9 @@ namespace dxvk {
|
|||||||
for (uint32_t i = 0; i < caps::MaxStreams; i++)
|
for (uint32_t i = 0; i < caps::MaxStreams; i++)
|
||||||
m_state.streamFreq[i] = 1;
|
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);
|
SetStateTexture(i, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
EmitCs([
|
EmitCs([
|
||||||
cSize = m_state.textures->size()
|
cSize = m_state.textures->size()
|
||||||
@ -7465,6 +7549,7 @@ namespace dxvk {
|
|||||||
desc.MultisampleQuality = pPresentationParameters->MultiSampleQuality;
|
desc.MultisampleQuality = pPresentationParameters->MultiSampleQuality;
|
||||||
desc.IsBackBuffer = FALSE;
|
desc.IsBackBuffer = FALSE;
|
||||||
desc.IsAttachmentOnly = TRUE;
|
desc.IsAttachmentOnly = TRUE;
|
||||||
|
desc.IsLosable = TRUE;
|
||||||
// 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;
|
||||||
|
|
||||||
@ -7474,6 +7559,7 @@ namespace dxvk {
|
|||||||
m_autoDepthStencil = new D3D9Surface(this, &desc, nullptr, nullptr);
|
m_autoDepthStencil = new D3D9Surface(this, &desc, nullptr, nullptr);
|
||||||
m_initializer->InitTexture(m_autoDepthStencil->GetCommonTexture());
|
m_initializer->InitTexture(m_autoDepthStencil->GetCommonTexture());
|
||||||
SetDepthStencilSurface(m_autoDepthStencil.ptr());
|
SetDepthStencilSurface(m_autoDepthStencil.ptr());
|
||||||
|
m_losableResourceCounter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetRenderTarget(0, m_implicitSwapchain->GetBackBuffer(0));
|
SetRenderTarget(0, m_implicitSwapchain->GetBackBuffer(0));
|
||||||
@ -7575,6 +7661,43 @@ namespace dxvk {
|
|||||||
#endif
|
#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
|
// D3D9 Device Specialization State
|
||||||
////////////////////////////////////
|
////////////////////////////////////
|
||||||
|
@ -879,6 +879,10 @@ namespace dxvk {
|
|||||||
|
|
||||||
void MarkTextureBindingDirty(IDirect3DBaseTexture9* texture);
|
void MarkTextureBindingDirty(IDirect3DBaseTexture9* texture);
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE SetRenderTargetInternal(
|
||||||
|
DWORD RenderTargetIndex,
|
||||||
|
IDirect3DSurface9* pRenderTarget);
|
||||||
|
|
||||||
D3D9DrawInfo GenerateDrawInfo(
|
D3D9DrawInfo GenerateDrawInfo(
|
||||||
D3DPRIMITIVETYPE PrimitiveType,
|
D3DPRIMITIVETYPE PrimitiveType,
|
||||||
UINT PrimitiveCount,
|
UINT PrimitiveCount,
|
||||||
@ -961,41 +965,20 @@ namespace dxvk {
|
|||||||
void TouchMappedTexture(D3D9CommonTexture* pTexture);
|
void TouchMappedTexture(D3D9CommonTexture* pTexture);
|
||||||
void RemoveMappedTexture(D3D9CommonTexture* pTexture);
|
void RemoveMappedTexture(D3D9CommonTexture* pTexture);
|
||||||
|
|
||||||
|
// Device Lost
|
||||||
bool IsDeviceLost() const {
|
bool IsDeviceLost() const {
|
||||||
return m_deviceLostState != D3D9DeviceLostState::Ok;
|
return m_deviceLostState != D3D9DeviceLostState::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotifyFullscreen(HWND window, bool fullscreen) {
|
void NotifyFullscreen(HWND window, bool fullscreen);
|
||||||
D3D9DeviceLock lock = LockDevice();
|
void NotifyWindowActivated(HWND window, bool activated);
|
||||||
|
|
||||||
if (fullscreen) {
|
void IncrementLosableCounter() {
|
||||||
if (unlikely(window != m_fullscreenWindow && m_fullscreenWindow != NULL)) {
|
m_losableResourceCounter++;
|
||||||
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 NotifyWindowActivated(HWND window, bool activated) {
|
void DecrementLosableCounter() {
|
||||||
D3D9DeviceLock lock = LockDevice();
|
m_losableResourceCounter--;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CanOnlySWVP() const {
|
bool CanOnlySWVP() const {
|
||||||
@ -1369,6 +1352,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
D3D9DeviceLostState m_deviceLostState = D3D9DeviceLostState::Ok;
|
D3D9DeviceLostState m_deviceLostState = D3D9DeviceLostState::Ok;
|
||||||
HWND m_fullscreenWindow = NULL;
|
HWND m_fullscreenWindow = NULL;
|
||||||
|
std::atomic<uint32_t> m_losableResourceCounter = { 0 };
|
||||||
|
|
||||||
#ifdef D3D9_ALLOW_UNMAPPING
|
#ifdef D3D9_ALLOW_UNMAPPING
|
||||||
lru_list<D3D9CommonTexture*> m_mappedTextures;
|
lru_list<D3D9CommonTexture*> m_mappedTextures;
|
||||||
|
@ -70,8 +70,8 @@ namespace dxvk {
|
|||||||
this->deviceLocalConstantBuffers = config.getOption<bool> ("d3d9.deviceLocalConstantBuffers", false);
|
this->deviceLocalConstantBuffers = config.getOption<bool> ("d3d9.deviceLocalConstantBuffers", false);
|
||||||
this->allowDirectBufferMapping = config.getOption<bool> ("d3d9.allowDirectBufferMapping", true);
|
this->allowDirectBufferMapping = config.getOption<bool> ("d3d9.allowDirectBufferMapping", true);
|
||||||
this->seamlessCubes = config.getOption<bool> ("d3d9.seamlessCubes", false);
|
this->seamlessCubes = config.getOption<bool> ("d3d9.seamlessCubes", false);
|
||||||
this->textureMemory = config.getOption<int32_t> ("d3d9.textureMemory", 100) << 20;
|
this->textureMemory = config.getOption<int32_t> ("d3d9.textureMemory", 100) << 20;
|
||||||
this->deviceLost = config.getOption<bool> ("d3d9.deviceLost", false);
|
this->deviceLossOnFocusLoss = config.getOption<bool> ("d3d9.deviceLossOnFocusLoss", false);
|
||||||
|
|
||||||
std::string floatEmulation = Config::toLower(config.getOption<std::string>("d3d9.floatEmulation", "auto"));
|
std::string floatEmulation = Config::toLower(config.getOption<std::string>("d3d9.floatEmulation", "auto"));
|
||||||
if (floatEmulation == "strict") {
|
if (floatEmulation == "strict") {
|
||||||
|
@ -143,7 +143,7 @@ namespace dxvk {
|
|||||||
std::string shaderDumpPath;
|
std::string shaderDumpPath;
|
||||||
|
|
||||||
/// Enable emulation of device loss when a fullscreen app loses focus
|
/// Enable emulation of device loss when a fullscreen app loses focus
|
||||||
bool deviceLost;
|
bool deviceLossOnFocusLoss;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,9 @@ namespace dxvk {
|
|||||||
CaptureType(Type);
|
CaptureType(Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
D3D9StateBlock::~D3D9StateBlock() {
|
||||||
|
m_parent->DecrementLosableCounter();
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE D3D9StateBlock::QueryInterface(
|
HRESULT STDMETHODCALLTYPE D3D9StateBlock::QueryInterface(
|
||||||
REFIID riid,
|
REFIID riid,
|
||||||
|
@ -89,6 +89,8 @@ namespace dxvk {
|
|||||||
|
|
||||||
D3D9StateBlock(D3D9DeviceEx* pDevice, D3D9StateBlockType Type);
|
D3D9StateBlock(D3D9DeviceEx* pDevice, D3D9StateBlockType Type);
|
||||||
|
|
||||||
|
~D3D9StateBlock();
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE QueryInterface(
|
HRESULT STDMETHODCALLTYPE QueryInterface(
|
||||||
REFIID riid,
|
REFIID riid,
|
||||||
void** ppvObject) final;
|
void** ppvObject) final;
|
||||||
|
@ -71,6 +71,8 @@ namespace dxvk {
|
|||||||
|
|
||||||
m_device->waitForSubmission(&m_presentStatus);
|
m_device->waitForSubmission(&m_presentStatus);
|
||||||
m_device->waitForIdle();
|
m_device->waitForIdle();
|
||||||
|
|
||||||
|
m_parent->DecrementLosableCounter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -436,6 +438,13 @@ namespace dxvk {
|
|||||||
return D3DERR_INVALIDCALL;
|
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());
|
*ppBackBuffer = ref(m_backBuffers[iBackBuffer].ptr());
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
}
|
}
|
||||||
@ -977,6 +986,7 @@ namespace dxvk {
|
|||||||
desc.Discard = FALSE;
|
desc.Discard = FALSE;
|
||||||
desc.IsBackBuffer = TRUE;
|
desc.IsBackBuffer = TRUE;
|
||||||
desc.IsAttachmentOnly = FALSE;
|
desc.IsAttachmentOnly = FALSE;
|
||||||
|
desc.IsLosable = TRUE;
|
||||||
// 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;
|
||||||
|
|
||||||
@ -984,6 +994,7 @@ namespace dxvk {
|
|||||||
D3D9Surface* surface;
|
D3D9Surface* surface;
|
||||||
try {
|
try {
|
||||||
surface = new D3D9Surface(m_parent, &desc, this, nullptr);
|
surface = new D3D9Surface(m_parent, &desc, this, nullptr);
|
||||||
|
m_parent->IncrementLosableCounter();
|
||||||
} catch (const DxvkError& e) {
|
} catch (const DxvkError& e) {
|
||||||
DestroyBackBuffers();
|
DestroyBackBuffers();
|
||||||
Logger::err(e.message());
|
Logger::err(e.message());
|
||||||
|
@ -120,6 +120,8 @@ namespace dxvk {
|
|||||||
|
|
||||||
bool HasFormatsUnlocked() const { return m_unlockAdditionalFormats; }
|
bool HasFormatsUnlocked() const { return m_unlockAdditionalFormats; }
|
||||||
|
|
||||||
|
void DestroyBackBuffers();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
enum BindingIds : uint32_t {
|
enum BindingIds : uint32_t {
|
||||||
@ -189,8 +191,6 @@ namespace dxvk {
|
|||||||
|
|
||||||
void CreateRenderTargetViews();
|
void CreateRenderTargetViews();
|
||||||
|
|
||||||
void DestroyBackBuffers();
|
|
||||||
|
|
||||||
HRESULT CreateBackBuffers(
|
HRESULT CreateBackBuffers(
|
||||||
uint32_t NumBackBuffers);
|
uint32_t NumBackBuffers);
|
||||||
|
|
||||||
|
@ -500,7 +500,7 @@ namespace dxvk {
|
|||||||
{ "d3d9.customVendorId", "1002" },
|
{ "d3d9.customVendorId", "1002" },
|
||||||
{ "dxgi.emulateUMA", "True" },
|
{ "dxgi.emulateUMA", "True" },
|
||||||
{ "d3d9.supportDFFormats", "False" },
|
{ "d3d9.supportDFFormats", "False" },
|
||||||
{ "d3d9.deviceLost", "True" },
|
{ "d3d9.deviceLostOnFocusLoss", "True" },
|
||||||
}} },
|
}} },
|
||||||
/* Battlefield 2 (bad z-pass) */
|
/* Battlefield 2 (bad z-pass) */
|
||||||
{ R"(\\BF2\.exe$)", {{
|
{ R"(\\BF2\.exe$)", {{
|
||||||
@ -754,7 +754,7 @@ namespace dxvk {
|
|||||||
/* DC Universe Online *
|
/* DC Universe Online *
|
||||||
* Freezes after alt tabbing */
|
* Freezes after alt tabbing */
|
||||||
{ R"(\\DCGAME\.EXE$)", {{
|
{ R"(\\DCGAME\.EXE$)", {{
|
||||||
{ "d3d9.deviceLost", "True" },
|
{ "d3d9.deviceLostOnFocusLoss", "True" },
|
||||||
}} },
|
}} },
|
||||||
/* Halo Online *
|
/* Halo Online *
|
||||||
* Black textures */
|
* Black textures */
|
||||||
|
Loading…
Reference in New Issue
Block a user