-
Notifications
You must be signed in to change notification settings - Fork 831
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[D3D9] Fix for back buffer data loss during D3D9 present #2967
Conversation
This might fix #2915 |
src/d3d9/d3d9_swapchain.cpp
Outdated
@@ -673,6 +673,24 @@ namespace dxvk { | |||
m_context->beginRecording( | |||
m_device->createCommandList()); | |||
|
|||
if (m_presentParams.SwapEffect != D3DSWAPEFFECT_DISCARD) | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (...) {
src/d3d9/d3d9_swapchain.cpp
Outdated
@@ -673,6 +673,24 @@ namespace dxvk { | |||
m_context->beginRecording( | |||
m_device->createCommandList()); | |||
|
|||
if (m_presentParams.SwapEffect != D3DSWAPEFFECT_DISCARD) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about flip?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to the D3D9 spec:
When a swap chain is created with a swap effect of D3DSWAPEFFECT_FLIP or D3DSWAPEFFECT_COPY, the runtime will guarantee that an IDirect3DDevice9::Present operation will not affect the content of any of the back buffers.
This implies that the content of the back buffer that is presented needs to be copied to the front buffer image instead of swapping the reference (this would hide the content of the back buffer from the application).
dd5103c
to
49854db
Compare
@@ -48,7 +48,6 @@ 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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also noExplicitFrontBuffer
variable declared in d3d9_options.h
5ae7cb4
to
49854db
Compare
? |
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove the reference to your internal issue in the commit message as it points to random issues here 🙂
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? |
@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 #2964 and the two from this into master and tried checking out the apitrace for the game Fantasy Ground Classic in this issue #1554 which is one of the two games the |
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
auto swapImageView = m_backBuffers[0]->GetImageView(false);
m_blitter->presentImage(m_context.ptr(),
m_imageViews.at(imageIndex), dstRect,
swapImageView, srcRect);
Shouldn't we present the front buffer here?
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. #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 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
That is pretty much exactly what DXVK already does. |
Superseded by #3392 |
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.