From 60c3c4f153d6eff0a588ac5d176dbfb22e5190d0 Mon Sep 17 00:00:00 2001 From: narzoul Date: Sat, 18 Nov 2017 22:28:04 +0100 Subject: [PATCH] Mitigate performance issues caused by slow surface interface release Releasing the last reference to a surface interface has a significant performance impact. Mitigating the issue by eliminating some frequent but unnecessary QueryInterface calls. Fixes most of the performance drop reported in issue #24. --- DDrawCompat/DDraw/DirectDrawSurface.cpp | 7 -- DDrawCompat/DDraw/DirectDrawSurface.h | 2 - DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp | 84 +++++++++---------- DDrawCompat/DDraw/Surfaces/PrimarySurface.h | 2 +- .../DDraw/Surfaces/PrimarySurfaceImpl.cpp | 2 - DDrawCompat/DDraw/Surfaces/Surface.cpp | 13 --- DDrawCompat/DDraw/Surfaces/Surface.h | 4 - DDrawCompat/DDraw/Surfaces/SurfaceImpl.cpp | 7 +- 8 files changed, 45 insertions(+), 76 deletions(-) diff --git a/DDrawCompat/DDraw/DirectDrawSurface.cpp b/DDrawCompat/DDraw/DirectDrawSurface.cpp index d10fad3..f116236 100644 --- a/DDrawCompat/DDraw/DirectDrawSurface.cpp +++ b/DDrawCompat/DDraw/DirectDrawSurface.cpp @@ -26,13 +26,6 @@ namespace namespace DDraw { - CompatPtr getDirectDraw(CompatRef surface) - { - CompatPtr dd; - surface.get().lpVtbl->GetDDInterface(&surface, reinterpret_cast(&dd.getRef())); - return dd; - } - template void DirectDrawSurface::setCompatVtable(Vtable& vtable) { diff --git a/DDrawCompat/DDraw/DirectDrawSurface.h b/DDrawCompat/DDraw/DirectDrawSurface.h index 935cfd2..b5d6d2f 100644 --- a/DDrawCompat/DDraw/DirectDrawSurface.h +++ b/DDrawCompat/DDraw/DirectDrawSurface.h @@ -8,8 +8,6 @@ namespace DDraw { - CompatPtr getDirectDraw(CompatRef surface); - template class DirectDrawSurface : public CompatVtable> { diff --git a/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp b/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp index c37c62a..3b4399a 100644 --- a/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp +++ b/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp @@ -8,9 +8,14 @@ namespace { DDSURFACEDESC2 g_primarySurfaceDesc = {}; - CompatWeakPtr g_gdiSurface = nullptr; - CompatWeakPtr g_primarySurface = nullptr; + CompatWeakPtr g_primarySurface = nullptr; + HANDLE g_gdiResourceHandle = nullptr; DWORD g_origCaps = 0; + + HANDLE getResourceHandle(IDirectDrawSurface7& surface) + { + return reinterpret_cast(&surface)[1][2]; + } } namespace DDraw @@ -24,7 +29,7 @@ namespace DDraw { Compat::LogEnter("PrimarySurface::~PrimarySurface"); - g_gdiSurface = nullptr; + g_gdiResourceHandle = nullptr; g_primarySurface = nullptr; g_origCaps = 0; s_palette = nullptr; @@ -68,9 +73,8 @@ namespace DDraw std::unique_ptr privateData(new PrimarySurface(Surface::getSurface(*surface))); attach(*surface7, privateData); - CompatPtr surface1(Compat::queryInterface(surface)); - g_gdiSurface = surface1; - g_primarySurface = surface1; + g_gdiResourceHandle = getResourceHandle(*surface7); + g_primarySurface = surface7; g_origCaps = origCaps; ZeroMemory(&g_primarySurfaceDesc, sizeof(g_primarySurfaceDesc)); @@ -105,11 +109,12 @@ namespace DDraw HRESULT PrimarySurface::flipToGdiSurface() { - if (!g_primarySurface) + CompatPtr gdiSurface; + if (!g_primarySurface || !(gdiSurface = getGdiSurface())) { return DDERR_NOTFOUND; } - return g_primarySurface.get()->lpVtbl->Flip(g_primarySurface, g_gdiSurface, DDFLIP_WAIT); + return g_primarySurface.get()->lpVtbl->Flip(g_primarySurface, gdiSurface, DDFLIP_WAIT); } const DDSURFACEDESC2& PrimarySurface::getDesc() @@ -118,18 +123,36 @@ namespace DDraw } CompatPtr PrimarySurface::getGdiSurface() - { - return CompatPtr::from(g_gdiSurface.get()); - } - - CompatPtr PrimarySurface::getPrimary() { if (!g_primarySurface) { return nullptr; } - return CompatPtr( - Compat::queryInterface(g_primarySurface.get())); + + DDSCAPS2 caps = {}; + caps.dwCaps = DDSCAPS_FLIP; + CompatWeakPtr surface(g_primarySurface); + + do + { + if (getResourceHandle(*surface) == g_gdiResourceHandle) + { + return CompatPtr::from(surface.get()); + } + + if (FAILED(surface->GetAttachedSurface(surface, &caps, &surface.getRef()))) + { + return nullptr; + } + surface->Release(surface); + } while (surface != g_primarySurface); + + return nullptr; + } + + CompatWeakPtr PrimarySurface::getPrimary() + { + return g_primarySurface; } DWORD PrimarySurface::getOrigCaps() @@ -162,37 +185,6 @@ namespace DDraw } while (surfacePtr && surfacePtr != &surface); } - void PrimarySurface::updateGdiSurfacePtr(IDirectDrawSurface* flipTargetOverride) - { - auto primary(CompatPtr::from(m_surface->getDirectDrawSurface().get())); - if (flipTargetOverride) - { - if (g_gdiSurface.get() == flipTargetOverride) - { - g_gdiSurface = primary; - } - else if (g_gdiSurface.get() == primary) - { - g_gdiSurface = flipTargetOverride; - } - return; - } - - DDSCAPS caps = {}; - caps.dwCaps = DDSCAPS_FLIP; - CompatPtr current(primary); - CompatPtr next; - HRESULT result = current->GetAttachedSurface(current, &caps, &next.getRef()); - while (SUCCEEDED(result) && next.get() != g_gdiSurface.get() && next.get() != primary) - { - current = next; - next.reset(); - result = current->GetAttachedSurface(current, &caps, &next.getRef()); - } - - g_gdiSurface = current; - } - CompatWeakPtr PrimarySurface::s_palette; PALETTEENTRY PrimarySurface::s_paletteEntries[256] = {}; std::vector> PrimarySurface::s_surfaceBuffers; diff --git a/DDrawCompat/DDraw/Surfaces/PrimarySurface.h b/DDrawCompat/DDraw/Surfaces/PrimarySurface.h index 0f7e82b..46912d6 100644 --- a/DDrawCompat/DDraw/Surfaces/PrimarySurface.h +++ b/DDrawCompat/DDraw/Surfaces/PrimarySurface.h @@ -19,7 +19,7 @@ namespace DDraw static HRESULT flipToGdiSurface(); static const DDSURFACEDESC2& getDesc(); static CompatPtr getGdiSurface(); - static CompatPtr getPrimary(); + static CompatWeakPtr getPrimary(); static DWORD getOrigCaps(); void updateGdiSurfacePtr(IDirectDrawSurface* flipTargetOverride); diff --git a/DDrawCompat/DDraw/Surfaces/PrimarySurfaceImpl.cpp b/DDrawCompat/DDraw/Surfaces/PrimarySurfaceImpl.cpp index 5c8007c..2046009 100644 --- a/DDrawCompat/DDraw/Surfaces/PrimarySurfaceImpl.cpp +++ b/DDrawCompat/DDraw/Surfaces/PrimarySurfaceImpl.cpp @@ -96,8 +96,6 @@ namespace DDraw result = RealPrimarySurface::flip(dwFlags); if (SUCCEEDED(result) && !isFlipEmulated) { - static_cast(m_data)->updateGdiSurfacePtr( - CompatPtr::from(lpDDSurfaceTargetOverride)); return DD_OK; } diff --git a/DDrawCompat/DDraw/Surfaces/Surface.cpp b/DDrawCompat/DDraw/Surfaces/Surface.cpp index 7ef3d1a..01ab9a4 100644 --- a/DDrawCompat/DDraw/Surfaces/Surface.cpp +++ b/DDrawCompat/DDraw/Surfaces/Surface.cpp @@ -108,7 +108,6 @@ namespace DDraw Surface::Surface() : m_ddObject(nullptr) - , m_dds(nullptr) , m_ddId() , m_refCount(0) { @@ -133,8 +132,6 @@ namespace DDraw privateData->m_impl4->m_data = privateData.get(); privateData->m_impl7->m_data = privateData.get(); - privateData->m_dds = CompatPtr( - Compat::queryInterface(&dds)); privateData->m_ddId = getDdIidFromVtablePtr(reinterpret_cast(dd.get())[0]); privateData->m_ddObject = DDraw::getDdObject(*CompatPtr(dd)); @@ -207,16 +204,6 @@ namespace DDraw template <> SurfaceImpl* Surface::getImpl() const { return m_impl7.get(); } - CompatPtr Surface::getDirectDraw() const - { - return DDraw::getDirectDraw(*getDirectDrawSurface()); - } - - CompatPtr Surface::getDirectDrawSurface() const - { - return CompatPtr(Compat::queryInterface(m_dds)); - } - template Surface* Surface::getSurface(TSurface& dds) { diff --git a/DDrawCompat/DDraw/Surfaces/Surface.h b/DDrawCompat/DDraw/Surfaces/Surface.h index f77ddd7..5f940b2 100644 --- a/DDrawCompat/DDraw/Surfaces/Surface.h +++ b/DDrawCompat/DDraw/Surfaces/Surface.h @@ -29,9 +29,6 @@ namespace DDraw template static Surface* getSurface(TSurface& dds); - CompatPtr getDirectDraw() const; - CompatPtr getDirectDrawSurface() const; - template SurfaceImpl* getImpl() const; @@ -55,7 +52,6 @@ namespace DDraw IDirectDrawSurface7* surface, DDSURFACEDESC2* desc, void* rootSurface); virtual void createImpl(); - IDirectDrawSurface* m_dds; IID m_ddId; DWORD m_refCount; }; diff --git a/DDrawCompat/DDraw/Surfaces/SurfaceImpl.cpp b/DDrawCompat/DDraw/Surfaces/SurfaceImpl.cpp index c95d356..3aab85f 100644 --- a/DDrawCompat/DDraw/Surfaces/SurfaceImpl.cpp +++ b/DDrawCompat/DDraw/Surfaces/SurfaceImpl.cpp @@ -121,7 +121,12 @@ namespace DDraw replDesc.ddpfPixelFormat = desc.ddpfPixelFormat; replDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; - DDraw::Repository::ScopedSurface replacementSurface(*m_data->getDirectDraw(), replDesc); + CompatPtr ddUnk; + GetDDInterface(surface, reinterpret_cast(&ddUnk.getRef())); + CompatPtr dd; + ddUnk->QueryInterface(ddUnk, IID_IDirectDraw7, reinterpret_cast(&dd.getRef())); + + DDraw::Repository::ScopedSurface replacementSurface(*dd, replDesc); if (replacementSurface.surface) { surface = CompatPtr::from(replacementSurface.surface.get());