mirror of
https://github.com/optiscaler/OptiScaler.git
synced 2026-08-24 07:06:33 +00:00
Added SK detection to ResizeBuffers(1) and Release. Should fix some resize based crashes (specially on crapcom games)
This commit is contained in:
@@ -28,6 +28,9 @@ static double _lastFrameTime = 0;
|
||||
static bool _dx11Device = false;
|
||||
static bool _dx12Device = false;
|
||||
|
||||
const GUID IID_IUnwrappedDXGISwapChain = {
|
||||
0xe8a33b4a, 0x1405, 0x424c, { 0xae, 0x88, 0xd, 0x3e, 0x9d, 0x46, 0xc9, 0x14 }
|
||||
};
|
||||
static HRESULT LocalPresent(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags,
|
||||
const DXGI_PRESENT_PARAMETERS* pPresentParameters, IUnknown* pDevice, HWND hWnd, bool isUWP)
|
||||
{
|
||||
@@ -473,6 +476,14 @@ ULONG STDMETHODCALLTYPE WrappedIDXGISwapChain4::Release()
|
||||
|
||||
auto refCount = _real->Release();
|
||||
|
||||
IDXGISwapChain* skSC = nullptr;
|
||||
if (_real->QueryInterface(IID_IUnwrappedDXGISwapChain, (void**) &skSC) == S_OK && skSC != nullptr)
|
||||
{
|
||||
skSC->Release();
|
||||
LOG_DEBUG("Found SK swapchain, skip releasing of main swapchain");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Release real swapchain, otherwise it can cause issues when re-creating swapchain with same handle
|
||||
while (refCount > 0)
|
||||
{
|
||||
@@ -480,6 +491,7 @@ ULONG STDMETHODCALLTYPE WrappedIDXGISwapChain4::Release()
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
refCount = _real->Release();
|
||||
}
|
||||
}
|
||||
|
||||
LOG_DEBUG("Real swapchain released, refCount: {}", refCount);
|
||||
|
||||
@@ -660,6 +672,51 @@ HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::ResizeBuffers(UINT BufferCount
|
||||
LOG_DEBUG("BufferCount: {0}, Width: {1}, Height: {2}, NewFormat: {3}, SwapChainFlags: {4:X}", BufferCount, Width,
|
||||
Height, (UINT) NewFormat, SwapChainFlags);
|
||||
|
||||
// Release swapchain backbuffers to prevent errors when resizing
|
||||
if (State::Instance().activeFgOutput != FGOutput::NoFG && State::Instance().activeFgOutput != FGOutput::Nukems &&
|
||||
State::Instance().currentFG != nullptr)
|
||||
{
|
||||
IDXGISwapChain* skSC = nullptr;
|
||||
if (_real->QueryInterface(IID_IUnwrappedDXGISwapChain, (void**) &skSC) == S_OK && skSC != nullptr)
|
||||
{
|
||||
skSC->Release();
|
||||
LOG_DEBUG("Found SK swapchain, skip releasing backbuffers of main swapchain");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEBUG("Releasing backbuffers, count: {}", desc.BufferCount);
|
||||
|
||||
for (UINT i = 0; i < desc.BufferCount; i++)
|
||||
{
|
||||
ID3D12Resource* backBuffer = nullptr;
|
||||
auto bbResult = _real->GetBuffer(i, IID_PPV_ARGS(&backBuffer));
|
||||
|
||||
if (bbResult == S_OK)
|
||||
{
|
||||
backBuffer->AddRef();
|
||||
|
||||
auto refCount = backBuffer->Release();
|
||||
refCount = backBuffer->Release();
|
||||
LOG_DEBUG("Current backbuffer {}, RefCount {}", i, refCount);
|
||||
|
||||
while (refCount > 1 && refCount < 4294967200ul)
|
||||
{
|
||||
refCount = backBuffer->Release();
|
||||
LOG_DEBUG("Releasing backbuffer {}, RefCount {}", i, refCount);
|
||||
}
|
||||
|
||||
LOG_DEBUG("Backbuffer {}, RefCount {}", i, refCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEBUG("GetBuffer failed for index {}: {:X}", i, (UINT) bbResult);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
if (Config::Instance()->FGDontUseSwapchainBuffers.value_or_default())
|
||||
{
|
||||
ScopedSkipHeapCapture skipHeapCapture {};
|
||||
@@ -970,6 +1027,64 @@ HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::ResizeBuffers1(UINT BufferCoun
|
||||
LOG_DEBUG("BufferCount: {}, Width: {}, Height: {}, NewFormat: {}, SwapChainFlags: {:X}", BufferCount, Width, Height,
|
||||
(UINT) Format, SwapChainFlags);
|
||||
|
||||
// Release swapchain backbuffers to prevent errors when resizing
|
||||
if (State::Instance().activeFgOutput != FGOutput::NoFG && State::Instance().activeFgOutput != FGOutput::Nukems &&
|
||||
State::Instance().currentFG != nullptr)
|
||||
{
|
||||
IDXGISwapChain* skSC = nullptr;
|
||||
if (_real->QueryInterface(IID_IUnwrappedDXGISwapChain, (void**) &skSC) == S_OK && skSC != nullptr)
|
||||
{
|
||||
skSC->Release();
|
||||
LOG_DEBUG(
|
||||
"Found SK swapchain, skip releasing backbuffersand using ResizeBuffers instead of ResizeBuffers1");
|
||||
|
||||
if (Config::Instance()->FGDontUseSwapchainBuffers.value_or_default())
|
||||
{
|
||||
ScopedSkipHeapCapture skipHeapCapture {};
|
||||
|
||||
_lastFlags = SwapChainFlags;
|
||||
result = _real3->ResizeBuffers(BufferCount, Width, Height, Format, SwapChainFlags);
|
||||
}
|
||||
else
|
||||
{
|
||||
_lastFlags = SwapChainFlags;
|
||||
result = _real3->ResizeBuffers(BufferCount, Width, Height, Format, SwapChainFlags);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEBUG("Releasing backbuffers, count: {}", desc.BufferCount);
|
||||
|
||||
for (UINT i = 0; i < desc.BufferCount; i++)
|
||||
{
|
||||
ID3D12Resource* backBuffer = nullptr;
|
||||
auto bbResult = _real->GetBuffer(i, IID_PPV_ARGS(&backBuffer));
|
||||
|
||||
if (bbResult == S_OK)
|
||||
{
|
||||
backBuffer->AddRef();
|
||||
|
||||
auto refCount = backBuffer->Release();
|
||||
refCount = backBuffer->Release();
|
||||
LOG_DEBUG("Current backbuffer {}, RefCount {}", i, refCount);
|
||||
|
||||
while (refCount > 1 && refCount < 4294967200ul)
|
||||
{
|
||||
refCount = backBuffer->Release();
|
||||
LOG_DEBUG("Releasing backbuffer {}, RefCount {}", i, refCount);
|
||||
}
|
||||
|
||||
LOG_DEBUG("Backbuffer {}, RefCount {}", i, refCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEBUG("GetBuffer failed for index {}: {:X}", i, (UINT) bbResult);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
if (Config::Instance()->FGDontUseSwapchainBuffers.value_or_default())
|
||||
{
|
||||
ScopedSkipHeapCapture skipHeapCapture {};
|
||||
@@ -984,6 +1099,7 @@ HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::ResizeBuffers1(UINT BufferCoun
|
||||
result = _real3->ResizeBuffers1(BufferCount, Width, Height, Format, SwapChainFlags, pCreationNodeMask,
|
||||
ppPresentQueue);
|
||||
}
|
||||
}
|
||||
|
||||
if (result == S_OK && State::Instance().currentFeature == nullptr)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user