mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-14 22:29:15 +01:00
[d3d9] Only have a single implicit swapchain
I am naive to think that this API is in any way sane, and that iSwapChains actually does what you would expect. Swapchains created by CreateAdditionalSwapchain[Ex] are not tracked in that figure... There can only ever be one. Great API. Very cool. This also adds and consolidates some missing thread synchronization on the swapchain functions (that should have already had it). (note: m_implicitSwapchain always exists, so we don't need to lock if that's all we call.)
This commit is contained in:
parent
e41640dcde
commit
528cacca5f
@ -161,12 +161,10 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetDisplayMode(UINT iSwapChain, D3DDISPLAYMODE* pMode) {
|
HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetDisplayMode(UINT iSwapChain, D3DDISPLAYMODE* pMode) {
|
||||||
D3D9DeviceLock lock = LockDevice();
|
if (unlikely(iSwapChain != 0))
|
||||||
|
return D3DERR_INVALIDCALL;
|
||||||
|
|
||||||
if (auto* swapchain = GetInternalSwapchain(iSwapChain))
|
return m_implicitSwapchain->GetDisplayMode(pMode);
|
||||||
return swapchain->GetDisplayMode(pMode);
|
|
||||||
|
|
||||||
return D3DERR_INVALIDCALL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -270,21 +268,24 @@ namespace dxvk {
|
|||||||
|
|
||||||
InitReturnPtr(pSwapChain);
|
InitReturnPtr(pSwapChain);
|
||||||
|
|
||||||
auto* swapchain = GetInternalSwapchain(iSwapChain);
|
if (unlikely(pSwapChain == nullptr))
|
||||||
|
|
||||||
if (unlikely(swapchain == nullptr || pSwapChain == nullptr))
|
|
||||||
return D3DERR_INVALIDCALL;
|
return D3DERR_INVALIDCALL;
|
||||||
|
|
||||||
*pSwapChain = static_cast<IDirect3DSwapChain9*>(ref(swapchain));
|
// This only returns the implicit swapchain...
|
||||||
|
|
||||||
|
if (unlikely(iSwapChain != 0))
|
||||||
|
return D3DERR_INVALIDCALL;
|
||||||
|
|
||||||
|
*pSwapChain = static_cast<IDirect3DSwapChain9*>(m_implicitSwapchain.ref());
|
||||||
|
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UINT STDMETHODCALLTYPE D3D9DeviceEx::GetNumberOfSwapChains() {
|
UINT STDMETHODCALLTYPE D3D9DeviceEx::GetNumberOfSwapChains() {
|
||||||
D3D9DeviceLock lock = LockDevice();
|
// This only counts the implicit swapchain...
|
||||||
|
|
||||||
return UINT(m_swapchains.size());
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -325,31 +326,23 @@ namespace dxvk {
|
|||||||
UINT iBackBuffer,
|
UINT iBackBuffer,
|
||||||
D3DBACKBUFFER_TYPE Type,
|
D3DBACKBUFFER_TYPE Type,
|
||||||
IDirect3DSurface9** ppBackBuffer) {
|
IDirect3DSurface9** ppBackBuffer) {
|
||||||
D3D9DeviceLock lock = LockDevice();
|
if (unlikely(iSwapChain != 0))
|
||||||
|
return D3DERR_INVALIDCALL;
|
||||||
|
|
||||||
InitReturnPtr(ppBackBuffer);
|
return m_implicitSwapchain->GetBackBuffer(iBackBuffer, Type, ppBackBuffer);
|
||||||
|
|
||||||
if (auto* swapchain = GetInternalSwapchain(iSwapChain))
|
|
||||||
return swapchain->GetBackBuffer(iBackBuffer, Type, ppBackBuffer);
|
|
||||||
|
|
||||||
return D3DERR_INVALIDCALL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetRasterStatus(UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
|
HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetRasterStatus(UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
|
||||||
D3D9DeviceLock lock = LockDevice();
|
if (unlikely(iSwapChain != 0))
|
||||||
|
return D3DERR_INVALIDCALL;
|
||||||
|
|
||||||
if (auto* swapchain = GetInternalSwapchain(iSwapChain))
|
return m_implicitSwapchain->GetRasterStatus(pRasterStatus);
|
||||||
return swapchain->GetRasterStatus(pRasterStatus);
|
|
||||||
|
|
||||||
return D3DERR_INVALIDCALL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetDialogBoxMode(BOOL bEnableDialogs) {
|
HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetDialogBoxMode(BOOL bEnableDialogs) {
|
||||||
D3D9DeviceLock lock = LockDevice();
|
return m_implicitSwapchain->SetDialogBoxMode(bEnableDialogs);
|
||||||
|
|
||||||
return GetInternalSwapchain(0)->SetDialogBoxMode(bEnableDialogs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -357,18 +350,18 @@ namespace dxvk {
|
|||||||
UINT iSwapChain,
|
UINT iSwapChain,
|
||||||
DWORD Flags,
|
DWORD Flags,
|
||||||
const D3DGAMMARAMP* pRamp) {
|
const D3DGAMMARAMP* pRamp) {
|
||||||
D3D9DeviceLock lock = LockDevice();
|
if (unlikely(iSwapChain != 0))
|
||||||
|
return;
|
||||||
|
|
||||||
if (auto* swapchain = GetInternalSwapchain(iSwapChain))
|
m_implicitSwapchain->SetGammaRamp(Flags, pRamp);
|
||||||
swapchain->SetGammaRamp(Flags, pRamp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void STDMETHODCALLTYPE D3D9DeviceEx::GetGammaRamp(UINT iSwapChain, D3DGAMMARAMP* pRamp) {
|
void STDMETHODCALLTYPE D3D9DeviceEx::GetGammaRamp(UINT iSwapChain, D3DGAMMARAMP* pRamp) {
|
||||||
D3D9DeviceLock lock = LockDevice();
|
if (unlikely(iSwapChain != 0))
|
||||||
|
return;
|
||||||
|
|
||||||
if (auto* swapchain = GetInternalSwapchain(iSwapChain))
|
m_implicitSwapchain->GetGammaRamp(pRamp);
|
||||||
swapchain->GetGammaRamp(pRamp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -818,12 +811,10 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetFrontBufferData(UINT iSwapChain, IDirect3DSurface9* pDestSurface) {
|
HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetFrontBufferData(UINT iSwapChain, IDirect3DSurface9* pDestSurface) {
|
||||||
D3D9DeviceLock lock = LockDevice();
|
if (unlikely(iSwapChain != 0))
|
||||||
|
return D3DERR_INVALIDCALL;
|
||||||
|
|
||||||
if (auto* swapchain = GetInternalSwapchain(iSwapChain))
|
return m_implicitSwapchain->GetFrontBufferData(pDestSurface);
|
||||||
return swapchain->GetFrontBufferData(pDestSurface);
|
|
||||||
|
|
||||||
return D3DERR_INVALIDCALL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3215,12 +3206,10 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE D3D9DeviceEx::WaitForVBlank(UINT iSwapChain) {
|
HRESULT STDMETHODCALLTYPE D3D9DeviceEx::WaitForVBlank(UINT iSwapChain) {
|
||||||
D3D9DeviceLock lock = LockDevice();
|
if (unlikely(iSwapChain != 0))
|
||||||
|
return D3DERR_INVALIDCALL;
|
||||||
|
|
||||||
if (auto* swapchain = GetInternalSwapchain(iSwapChain))
|
return m_implicitSwapchain->WaitForVBlank();
|
||||||
return swapchain->WaitForVBlank();
|
|
||||||
|
|
||||||
return D3DERR_INVALIDCALL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3268,9 +3257,7 @@ namespace dxvk {
|
|||||||
HWND hDestWindowOverride,
|
HWND hDestWindowOverride,
|
||||||
const RGNDATA* pDirtyRegion,
|
const RGNDATA* pDirtyRegion,
|
||||||
DWORD dwFlags) {
|
DWORD dwFlags) {
|
||||||
D3D9DeviceLock lock = LockDevice();
|
return m_implicitSwapchain->Present(
|
||||||
|
|
||||||
return GetInternalSwapchain(0)->Present(
|
|
||||||
pSourceRect,
|
pSourceRect,
|
||||||
pDestRect,
|
pDestRect,
|
||||||
hDestWindowOverride,
|
hDestWindowOverride,
|
||||||
@ -3429,12 +3416,10 @@ namespace dxvk {
|
|||||||
UINT iSwapChain,
|
UINT iSwapChain,
|
||||||
D3DDISPLAYMODEEX* pMode,
|
D3DDISPLAYMODEEX* pMode,
|
||||||
D3DDISPLAYROTATION* pRotation) {
|
D3DDISPLAYROTATION* pRotation) {
|
||||||
D3D9DeviceLock lock = LockDevice();
|
if (unlikely(iSwapChain != 0))
|
||||||
|
return D3DERR_INVALIDCALL;
|
||||||
|
|
||||||
if (auto* swapchain = GetInternalSwapchain(iSwapChain))
|
return m_implicitSwapchain->GetDisplayModeEx(pMode, pRotation);
|
||||||
return swapchain->GetDisplayModeEx(pMode, pRotation);
|
|
||||||
|
|
||||||
return D3DERR_INVALIDCALL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3449,14 +3434,12 @@ namespace dxvk {
|
|||||||
if (ppSwapChain == nullptr || pPresentationParameters == nullptr)
|
if (ppSwapChain == nullptr || pPresentationParameters == nullptr)
|
||||||
return D3DERR_INVALIDCALL;
|
return D3DERR_INVALIDCALL;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < m_swapchains.size(); i++)
|
m_implicitSwapchain->Invalidate(pPresentationParameters->hDeviceWindow);
|
||||||
GetInternalSwapchain(i)->Invalidate(pPresentationParameters->hDeviceWindow);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto* swapchain = new D3D9SwapChainEx(this, pPresentationParameters, pFullscreenDisplayMode);
|
auto* swapchain = new D3D9SwapChainEx(this, pPresentationParameters, pFullscreenDisplayMode);
|
||||||
*ppSwapChain = ref(swapchain);
|
*ppSwapChain = ref(swapchain);
|
||||||
|
|
||||||
m_swapchains.push_back(swapchain);
|
|
||||||
swapchain->AddRefPrivate();
|
swapchain->AddRefPrivate();
|
||||||
}
|
}
|
||||||
catch (const DxvkError & e) {
|
catch (const DxvkError & e) {
|
||||||
@ -3732,14 +3715,6 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
D3D9SwapChainEx* D3D9DeviceEx::GetInternalSwapchain(UINT index) {
|
|
||||||
if (unlikely(index >= m_swapchains.size()))
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return m_swapchains[index].ptr();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool D3D9DeviceEx::ShouldRecord() {
|
bool D3D9DeviceEx::ShouldRecord() {
|
||||||
return m_recorder != nullptr && !m_recorder->IsApplying();
|
return m_recorder != nullptr && !m_recorder->IsApplying();
|
||||||
}
|
}
|
||||||
@ -6646,10 +6621,10 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto* implicitSwapchain = GetInternalSwapchain(0))
|
if (m_implicitSwapchain != nullptr)
|
||||||
implicitSwapchain->Reset(pPresentationParameters, pFullscreenDisplayMode);
|
m_implicitSwapchain->Reset(pPresentationParameters, pFullscreenDisplayMode);
|
||||||
else
|
else
|
||||||
m_swapchains.emplace_back(new D3D9SwapChainEx(this, pPresentationParameters, pFullscreenDisplayMode));
|
m_implicitSwapchain = new D3D9SwapChainEx(this, pPresentationParameters, pFullscreenDisplayMode);
|
||||||
|
|
||||||
if (pPresentationParameters->EnableAutoDepthStencil) {
|
if (pPresentationParameters->EnableAutoDepthStencil) {
|
||||||
D3D9_COMMON_TEXTURE_DESC desc;
|
D3D9_COMMON_TEXTURE_DESC desc;
|
||||||
@ -6673,7 +6648,7 @@ namespace dxvk {
|
|||||||
SetDepthStencilSurface(m_autoDepthStencil.ptr());
|
SetDepthStencilSurface(m_autoDepthStencil.ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
SetRenderTarget(0, GetInternalSwapchain(0)->GetBackBuffer(0));
|
SetRenderTarget(0, m_implicitSwapchain->GetBackBuffer(0));
|
||||||
|
|
||||||
// Force this if we end up binding the same RT to make scissor change go into effect.
|
// Force this if we end up binding the same RT to make scissor change go into effect.
|
||||||
BindViewportAndScissor();
|
BindViewportAndScissor();
|
||||||
|
@ -1002,9 +1002,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
Com<D3D9Surface, false> m_autoDepthStencil;
|
Com<D3D9Surface, false> m_autoDepthStencil;
|
||||||
|
|
||||||
std::vector<
|
Com<D3D9SwapChainEx, false> m_implicitSwapchain;
|
||||||
Com<D3D9SwapChainEx,
|
|
||||||
false>> m_swapchains;
|
|
||||||
|
|
||||||
std::unordered_map<
|
std::unordered_map<
|
||||||
D3D9SamplerKey,
|
D3D9SamplerKey,
|
||||||
@ -1058,8 +1056,6 @@ namespace dxvk {
|
|||||||
|
|
||||||
D3D9UPBufferSlice AllocUpBuffer(VkDeviceSize size);
|
D3D9UPBufferSlice AllocUpBuffer(VkDeviceSize size);
|
||||||
|
|
||||||
D3D9SwapChainEx* GetInternalSwapchain(UINT index);
|
|
||||||
|
|
||||||
bool ShouldRecord();
|
bool ShouldRecord();
|
||||||
|
|
||||||
HRESULT CreateShaderModule(
|
HRESULT CreateShaderModule(
|
||||||
|
@ -89,7 +89,7 @@ namespace dxvk {
|
|||||||
HWND hDestWindowOverride,
|
HWND hDestWindowOverride,
|
||||||
const RGNDATA* pDirtyRegion,
|
const RGNDATA* pDirtyRegion,
|
||||||
DWORD dwFlags) {
|
DWORD dwFlags) {
|
||||||
auto lock = m_parent->LockDevice();
|
D3D9DeviceLock lock = m_parent->LockDevice();
|
||||||
|
|
||||||
uint32_t presentInterval = m_presentParams.PresentationInterval;
|
uint32_t presentInterval = m_presentParams.PresentationInterval;
|
||||||
|
|
||||||
@ -152,7 +152,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE D3D9SwapChainEx::GetFrontBufferData(IDirect3DSurface9* pDestSurface) {
|
HRESULT STDMETHODCALLTYPE D3D9SwapChainEx::GetFrontBufferData(IDirect3DSurface9* pDestSurface) {
|
||||||
auto lock = m_parent->LockDevice();
|
D3D9DeviceLock lock = m_parent->LockDevice();
|
||||||
|
|
||||||
// This function can do absolutely everything!
|
// This function can do absolutely everything!
|
||||||
// Copies the front buffer between formats with an implicit resolve.
|
// Copies the front buffer between formats with an implicit resolve.
|
||||||
@ -331,6 +331,9 @@ namespace dxvk {
|
|||||||
UINT iBackBuffer,
|
UINT iBackBuffer,
|
||||||
D3DBACKBUFFER_TYPE Type,
|
D3DBACKBUFFER_TYPE Type,
|
||||||
IDirect3DSurface9** ppBackBuffer) {
|
IDirect3DSurface9** ppBackBuffer) {
|
||||||
|
// Could be doing a device reset...
|
||||||
|
D3D9DeviceLock lock = m_parent->LockDevice();
|
||||||
|
|
||||||
if (unlikely(ppBackBuffer == nullptr))
|
if (unlikely(ppBackBuffer == nullptr))
|
||||||
return D3DERR_INVALIDCALL;
|
return D3DERR_INVALIDCALL;
|
||||||
|
|
||||||
@ -454,7 +457,7 @@ namespace dxvk {
|
|||||||
void D3D9SwapChainEx::Reset(
|
void D3D9SwapChainEx::Reset(
|
||||||
D3DPRESENT_PARAMETERS* pPresentParams,
|
D3DPRESENT_PARAMETERS* pPresentParams,
|
||||||
D3DDISPLAYMODEEX* pFullscreenDisplayMode) {
|
D3DDISPLAYMODEEX* pFullscreenDisplayMode) {
|
||||||
auto lock = m_parent->LockDevice();
|
D3D9DeviceLock lock = m_parent->LockDevice();
|
||||||
|
|
||||||
this->SynchronizePresent();
|
this->SynchronizePresent();
|
||||||
this->NormalizePresentParameters(pPresentParams);
|
this->NormalizePresentParameters(pPresentParams);
|
||||||
@ -516,6 +519,8 @@ namespace dxvk {
|
|||||||
void D3D9SwapChainEx::SetGammaRamp(
|
void D3D9SwapChainEx::SetGammaRamp(
|
||||||
DWORD Flags,
|
DWORD Flags,
|
||||||
const D3DGAMMARAMP* pRamp) {
|
const D3DGAMMARAMP* pRamp) {
|
||||||
|
D3D9DeviceLock lock = m_parent->LockDevice();
|
||||||
|
|
||||||
if (unlikely(pRamp == nullptr))
|
if (unlikely(pRamp == nullptr))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -546,6 +551,8 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
void D3D9SwapChainEx::GetGammaRamp(D3DGAMMARAMP* pRamp) {
|
void D3D9SwapChainEx::GetGammaRamp(D3DGAMMARAMP* pRamp) {
|
||||||
|
D3D9DeviceLock lock = m_parent->LockDevice();
|
||||||
|
|
||||||
if (likely(pRamp != nullptr))
|
if (likely(pRamp != nullptr))
|
||||||
*pRamp = m_ramp;
|
*pRamp = m_ramp;
|
||||||
}
|
}
|
||||||
@ -565,6 +572,8 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
HRESULT D3D9SwapChainEx::SetDialogBoxMode(bool bEnableDialogs) {
|
HRESULT D3D9SwapChainEx::SetDialogBoxMode(bool bEnableDialogs) {
|
||||||
|
D3D9DeviceLock lock = m_parent->LockDevice();
|
||||||
|
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/d3d9/nf-d3d9-idirect3ddevice9-setdialogboxmode
|
// https://docs.microsoft.com/en-us/windows/win32/api/d3d9/nf-d3d9-idirect3ddevice9-setdialogboxmode
|
||||||
// The MSDN documentation says this will error out under many weird conditions.
|
// The MSDN documentation says this will error out under many weird conditions.
|
||||||
// However it doesn't appear to error at all in any of my tests of these
|
// However it doesn't appear to error at all in any of my tests of these
|
||||||
|
Loading…
x
Reference in New Issue
Block a user