1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-03-03 16:29:15 +01:00

[d3d9] Refactor presenter management

There's basically no reason to ever recreate a presenter for an already
managed window with the new code.
This commit is contained in:
Philip Rebohle 2025-01-15 18:05:47 +01:00 committed by Philip Rebohle
parent 785649f3b8
commit c43cf6895b
2 changed files with 50 additions and 61 deletions

View File

@ -36,9 +36,6 @@ namespace dxvk {
UpdatePresentRegion(nullptr, nullptr);
if (m_window)
CreatePresenter();
if (FAILED(CreateBackBuffers(m_presentParams.BackBufferCount, m_presentParams.Flags)))
throw DxvkError("D3D9: Failed to create swapchain backbuffers");
@ -73,8 +70,12 @@ namespace dxvk {
ResetWindowProc(m_window);
RestoreDisplayMode(m_monitor);
m_device->waitForSubmission(&m_presentStatus);
m_device->waitForIdle();
for (auto& p : m_presenters) {
if (p.second.presenter) {
p.second.presenter->destroyResources();
p.second.presenter = nullptr;
}
}
m_parent->DecrementLosableCounter();
}
@ -147,18 +148,13 @@ namespace dxvk {
if (hDestWindowOverride != nullptr)
m_window = hDestWindowOverride;
if (m_window == nullptr)
if (!UpdateWindowCtx())
return D3D_OK;
UpdateWindowCtx();
if (options->deferSurfaceCreation && m_parent->IsDeviceReset())
m_wctx->presenter->invalidateSurface();
bool recreate = !m_wctx->presenter;
if (options->deferSurfaceCreation)
recreate |= m_parent->IsDeviceReset();
if (m_wctx->presenter)
m_wctx->presenter->setSyncInterval(presentInterval);
m_wctx->presenter->setSyncInterval(presentInterval);
UpdatePresentRegion(pSourceRect, pDestRect);
UpdatePresentParameters();
@ -170,9 +166,6 @@ namespace dxvk {
#endif
try {
if (recreate)
RecreateSurface();
// We aren't going to device loss simply because
// 99% of D3D9 games don't handle this properly and
// just end up crashing (like with alt-tab loss)
@ -716,16 +709,21 @@ namespace dxvk {
void D3D9SwapChainEx::Invalidate(HWND hWindow) {
if (hWindow == nullptr)
if (!hWindow)
hWindow = m_parent->GetWindow();
if (m_presenters.count(hWindow)) {
if (m_wctx == &m_presenters[hWindow])
m_wctx = nullptr;
m_presenters.erase(hWindow);
auto entry = m_presenters.find(hWindow);
m_device->waitForSubmission(&m_presentStatus);
m_device->waitForIdle();
if (entry != m_presenters.end()) {
if (entry->second.presenter) {
entry->second.presenter->destroyResources();
entry->second.presenter = nullptr;
}
if (m_wctx == &entry->second)
m_wctx = nullptr;
m_presenters.erase(entry);
}
}
@ -907,28 +905,13 @@ namespace dxvk {
}
void D3D9SwapChainEx::RecreateSurface() {
if (m_wctx->presenter)
m_wctx->presenter->invalidateSurface();
else
CreatePresenter();
}
void D3D9SwapChainEx::CreatePresenter() {
// Ensure that we can safely destroy the swap chain
m_device->waitForSubmission(&m_presentStatus);
m_device->waitForIdle();
m_presentStatus.result = VK_SUCCESS;
Rc<Presenter> D3D9SwapChainEx::CreatePresenter(HWND Window, Rc<sync::Signal> Signal) {
PresenterDesc presenterDesc;
presenterDesc.deferSurfaceCreation = m_parent->GetOptions()->deferSurfaceCreation;
m_wctx->presenter = new Presenter(m_device,
m_wctx->frameLatencySignal, presenterDesc, [
Rc<Presenter> presenter = new Presenter(m_device, Signal, presenterDesc, [
cDevice = m_device,
cWindow = m_window
cWindow = Window
] (VkSurfaceKHR* surface) {
auto vki = cDevice->adapter()->vki();
@ -938,11 +921,13 @@ namespace dxvk {
surface);
});
m_wctx->presenter->setSurfaceExtent(m_swapchainExtent);
m_wctx->presenter->setSurfaceFormat(GetSurfaceFormat());
presenter->setSurfaceExtent(m_swapchainExtent);
presenter->setSurfaceFormat(GetSurfaceFormat());
if (m_hdrMetadata)
m_wctx->presenter->setHdrMetadata(*m_hdrMetadata);
presenter->setHdrMetadata(*m_hdrMetadata);
return presenter;
}
@ -954,20 +939,24 @@ namespace dxvk {
}
void D3D9SwapChainEx::UpdateWindowCtx() {
if (m_window == nullptr)
return;
bool D3D9SwapChainEx::UpdateWindowCtx() {
if (!m_window)
return false;
if (!m_presenters.count(m_window)) {
auto res = m_presenters.emplace(
auto entry = m_presenters.find(m_window);
if (entry == m_presenters.end()) {
entry = m_presenters.emplace(
std::piecewise_construct,
std::forward_as_tuple(m_window),
std::forward_as_tuple());
std::forward_as_tuple()).first;
auto& wctx = res.first->second;
wctx.frameLatencySignal = new sync::Fence(wctx.frameId);
entry->second.frameLatencySignal = new sync::Fence(entry->second.frameId);
entry->second.presenter = CreatePresenter(m_window, entry->second.frameLatencySignal);
}
m_wctx = &m_presenters[m_window];
m_wctx = &entry->second;
return true;
}
@ -1280,7 +1269,7 @@ namespace dxvk {
}
void D3D9SwapChainEx::UpdatePresentParameters() {
if (m_wctx && m_wctx->presenter) {
if (m_wctx) {
m_wctx->presenter->setSurfaceExtent(m_swapchainExtent);
m_wctx->presenter->setSurfaceFormat(GetSurfaceFormat());
}
@ -1326,7 +1315,7 @@ namespace dxvk {
m_swapchain->m_colorspace = ColorSpace;
if (m_swapchain->m_wctx && m_swapchain->m_wctx->presenter)
if (m_swapchain->m_wctx)
m_swapchain->m_wctx->presenter->setSurfaceFormat(m_swapchain->GetSurfaceFormat());
return S_OK;
@ -1339,7 +1328,7 @@ namespace dxvk {
m_swapchain->m_hdrMetadata = *pHDRMetadata;
if (m_swapchain->m_wctx && m_swapchain->m_wctx->presenter)
if (m_swapchain->m_wctx)
m_swapchain->m_wctx->presenter->setHdrMetadata(*pHDRMetadata);
return S_OK;

View File

@ -135,7 +135,7 @@ namespace dxvk {
void SetApiName(const char* name);
void UpdateWindowCtx();
bool UpdateWindowCtx();
private:
@ -189,9 +189,9 @@ namespace dxvk {
void SynchronizePresent();
void RecreateSurface();
void CreatePresenter();
Rc<Presenter> CreatePresenter(
HWND Window,
Rc<sync::Signal> Signal);
HRESULT CreateBackBuffers(
uint32_t NumBackBuffers,