[D3D9] Fix for back buffer data loss during D3D9 present
Acording to the D3D9 spec the content of the back buffer can be altered only if the SwapEffect is D3DSWAPEFFECT_DISCARD. The current implementation of the front buffer caused the previous back buffers to have their content lost.
This change keeps a similar present back buffer swapping logic for D3DSWAPEFFECT_DISCARD. For other swap effects the front buffer is a copy of the last presented back buffer.
This might fix #2915
?
First we need to merge https://github.com/doitsujin/dxvk/pull/2964 to merge this.
Our coleague, responsible for https://github.com/doitsujin/dxvk/pull/2964, is on sick leave, will be back 10.10.2022
Any update on this PR and related PR? Hoping this would fix some dx9 games that have the partial black screen issue and doesn't get fixed with d3d9.shaderModel = 1.
@frosty5689 what games have this issue? If they don't already have an issue report then it would be great if you could make some.
@adamjer Sorry for the relative silence in this PR and the others. There is currently a semi code freeze until the next release, which hopefully shouldn't be too long.
I finally got around to try and help the devs test this. I picked the commit from https://github.com/doitsujin/dxvk/pull/2964 and the two from this into master and tried checking out the apitrace for the game Fantasy Ground Classic in this issue https://github.com/doitsujin/dxvk/issues/1554 which is one of the two games the d3d9.noExplicitFrontBuffer configs were supposed to help with.
It seem that this PR reintroduces the original issue where the game will have the backgrounds blinking black.
I'd like to come back to this after DXVK 2.0 is released, there is a lot that can and probably will regress from this either in perf or functionality.
We've done a bunch of testing in some issues that we had hoped might have been fixed or affected by this PR (plus #2964). Posting the tested issues here for easy overview so it won't get lost. Most of these are believed to be partial presentation issues and weren't expected to change, but were given a spin anyway.
https://github.com/doitsujin/dxvk/issues/3250 no change. Thx @besentv https://github.com/doitsujin/dxvk/issues/2915 no change https://github.com/doitsujin/dxvk/issues/2732 no change https://github.com/doitsujin/dxvk/issues/2240 no change https://github.com/doitsujin/dxvk/issues/1476 no change https://github.com/doitsujin/dxvk/issues/2568 no change https://github.com/doitsujin/dxvk/issues/2542 no change https://github.com/doitsujin/dxvk/issues/2456 no change https://github.com/doitsujin/dxvk/issues/3116 no change https://github.com/doitsujin/dxvk/issues/3196 no change https://github.com/doitsujin/dxvk/issues/3208 no change https://github.com/doitsujin/dxvk/issues/3206 no change in apitrace https://github.com/doitsujin/dxvk/issues/2756 no change https://github.com/doitsujin/dxvk/issues/1554 apitrace regresses. Can't reproduce in launcher https://github.com/doitsujin/dxvk/issues/2860 Untested. Wine issue https://github.com/doitsujin/dxvk/issues/3005 Untested. Black screen https://github.com/doitsujin/dxvk/issues/3238 fixes issue 🎉 https://github.com/doitsujin/dxvk/issues/1481 fixes issue 🎉
#3250 no change. Thx @besentv
This PR can't help Zusi because Zusi uses the DISCARD swapeffect (last time I checked, probably because it wants MSAA) but still expects COPY semantics, i.e. unchanged backbuffer contents after Present. This usually works fine on Windows in windowed mode, even though it is invalid use of the DirectX API. (Apparently flipping buffers would not help with performance when compositing is required, so there is no buffer flipping in windowed mode?)
I guess Zusi is not the only application (ab)using this behavior, so some kind of workaround would probably still be needed even when non-DISCARD swap effects are implemented correctly. So I'd ask to keep the noExplicitFrontBuffer config option that is removed in this PR. It would make dxvk unusable for Zusi otherwise.
Or maybe GetFrontBufferData() could be implemented similar to this to get rid of the "internal" dxvk frontbuffer, then the "internal" swapchain could be backbuffers only, so no "internal" flipping when there's only 1 backbuffer. I believe most/all (?) Vulkan implementations support VK_IMAGE_USAGE_TRANSFER_SRC_BIT for swapchain images.
@w-flo Thank you for your thoughts on some of these issues. I don't have the technical knowledge to add anything myself to what you write sadly hehe. If you want to then i am sure you are welcome to join the Linux Gaming Dev discord where some might have more insightful comments than me.
@Blisto91
Thank you for your thoughts on some of these issues. I don't have the technical knowledge to add anything myself to what you write sadly hehe. If you want to then i am sure you are welcome to join the Linux Gaming Dev discord where some might have more insightful comments than me.
If only other users was not able to read the issues in this repo and leave comments. This is perfect place for technical information.
@Blisto91 To be honest I'm not sure if I have the technical knowledge to do it either, and I'm not sure if it's even possible in a way that is "similar enough" to Windows behavior while not affecting performance in a bad way. I want to give it a try, maybe I can get some proof of concept to work. Or maybe the only feasible way forward is to keep the current "you can take a screenshot using GetFrontBufferData(), or you can avoid back buffer loss, but not both" situation (and maybe a third option "you can actually have both, but performance will suffer"?). Plus game-specific settings for which of the two/three options games prefer.
Also I don't have a discord account and I'm reluctant to create one.
D3DSWAPEFFECT_FLIP
The swap chain might include multiple back buffers and is best envisaged as a circular queue that includes the front buffer. Within this queue, the back buffers are always numbered sequentially from 0 to (n - 1), where n is the number of back buffers, so that 0 denotes the least recently presented buffer. When Present is invoked, the queue is "rotated" so that the front buffer becomes back buffer (n - 1), while the back buffer 0 becomes the new front buffer.
That is pretty much exactly what DXVK already does.
Superseded by #3392