1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-19 05:52:11 +01:00

[d3d9] Add option to disable the explicit frontbuffer

The Vulkan swapchain is unaffected by this, but we don't create an
"internal" frontbuffer in D3D9SwapChainEx if this option is set. This
breaks GetFrontBufferData (which returns backbuffer data if the option
is enabled), but it disables front/backbuffer flipping.

Most windows drivers apparently always use the same backbuffer for all
frames in windowed mode. At least one game (ZUSI 3) seems to rely on
this behavior, and only redraws dirty regions for each frame instead of
redrawing everything. With buffer flips, this leads to flickering. When
enabling this new noExplicitFrontBuffer option, the flickering
disappears.
This commit is contained in:
Florian Will 2020-01-25 11:08:17 +01:00 committed by Joshua Ashton
parent 6a8933cf31
commit 1a4b15a82d
3 changed files with 14 additions and 2 deletions

View File

@ -47,6 +47,7 @@ namespace dxvk {
this->strictPow = config.getOption<bool> ("d3d9.strictPow", true);
this->lenientClear = config.getOption<bool> ("d3d9.lenientClear", false);
this->numBackBuffers = config.getOption<int32_t> ("d3d9.numBackBuffers", 0);
this->noExplicitFrontBuffer = config.getOption<bool> ("d3d9.noExplicitFrontBuffer", false);
this->deferSurfaceCreation = config.getOption<bool> ("d3d9.deferSurfaceCreation", false);
this->samplerAnisotropy = config.getOption<int32_t> ("d3d9.samplerAnisotropy", -1);
this->maxAvailableMemory = config.getOption<int32_t> ("d3d9.maxAvailableMemory", 4096);

View File

@ -55,6 +55,16 @@ namespace dxvk {
/// Overrides buffer count in present parameters.
int32_t numBackBuffers;
/// Don't create an explicit front buffer in our own swapchain. The Vulkan swapchain is unaffected.
/// Some games don't handle front/backbuffer flipping very well because they don't always redraw
/// each frame completely, and rely on old pixel data from the previous frame to still be there.
/// When this option is set and a game only requests one backbuffer, there will be no flipping in
/// our own swapchain, so the game will always draw to the same buffer and can rely on old pixel
/// data to still be there after a Present call.
/// This means that D3D9SwapChainEx::GetFrontBufferData returns data from the backbuffer of the
/// previous frame, which is the same as the current backbuffer if only 1 backbuffer was requested.
bool noExplicitFrontBuffer;
/// Defer surface creation
bool deferSurfaceCreation;

View File

@ -208,7 +208,7 @@ namespace dxvk {
return D3DERR_INVALIDCALL;
D3D9CommonTexture* dstTexInfo = dst->GetCommonTexture();
D3D9CommonTexture* srcTexInfo = m_backBuffers[m_presentParams.BackBufferCount]->GetCommonTexture();
D3D9CommonTexture* srcTexInfo = m_backBuffers.back()->GetCommonTexture();
if (unlikely(dstTexInfo->Desc()->Pool != D3DPOOL_SYSTEMMEM))
return D3DERR_INVALIDCALL;
@ -930,8 +930,9 @@ namespace dxvk {
m_resolveImage = nullptr;
m_resolveImageView = nullptr;
int NumFrontBuffer = m_parent->GetOptions()->noExplicitFrontBuffer ? 0 : 1;
m_backBuffers.clear();
m_backBuffers.resize(NumBackBuffers + 1);
m_backBuffers.resize(NumBackBuffers + NumFrontBuffer);
// Create new back buffer
D3D9_COMMON_TEXTURE_DESC desc;