-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Dynamic capture format selection (IDXGIOutput5) #654
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
Conversation
|
|
||
| // Now that we know the capture format, we can finish creating the image | ||
| if(complete_img(img, false)) { | ||
| return capture_e::error; |
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.
There's a problem with hardware capture on my RX 6600. Using Gravity Mark in Vulkan mode, clicking "Demo" sometimes (but not always) triggers the stream to end with:
[2022:12:30:11:12:38]: Error: display_vram_t::complete_img() called with unknown capture format!
The failure happen when snapshot() is called with format set to DXGI_FORMAT_UNKNOWN, but the format doesn't get updated due to frame_update_flag being false (which seems to trigger easily with Gravity Mark's Initializing screen presumably due it being low framerate with a static background).
The issue can be resolved by moving the complete_img() check into the frame_update_flag condition directly above OR changing the error condition to a timeout or OK.
Any of those changes avoids the error, but it brings back a bug that existed before (and was fixed by) your earlier format selection fix. In Gravity Mark, if I move the mouse on the "Initializing" screen, the mouse pointer will have a ghosting effect, perhaps suggesting a format mismatch for the pointer. I don't know precisely how to fix this properly, but if you change the check here to if (update_flag) { instead of if (frame_update_flag) {, it fixes the pointer ghosting.
Edit: to clarify, the ghosting effect occurs only on the "Initializing" screen, and not when the demo itself start running. I also saw the ghosting issue sometimes when entering fullscreen in games, but it didn't happen consistently.
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.
I don't know precisely how to fix this properly, but if you change the check here to if (update_flag) { instead of if (frame_update_flag) {, it fixes the pointer ghosting.
This was actually the correct fix. We've been breaking the rules for lifetime of the desktop image we get from the Desktop Duplication API. I'm not sure why this change specifically exposed it (or why my original format change "fixed" it).
The ReleaseFrame() docs say:
After the frame is released, the surface that contains the desktop bitmap becomes invalid; you will not be able to use the surface in a DirectX graphics operation.
Yet we're holding on to that ID3D11Texture2D to copy into our buffer when AcquireNextFrame() says the desktop image wasn't updated. We depend on the CopyResource() call to initialize the destination texture with an updated image before we draw the mouse on top. However, if the old source texture is invalid (which would be the case for a mouse-only update), that copy silently fails (leaving the old contents of the image intact, including the old mouse cursor drawn into it) and we draw the mouse again at the new location.
I pushed a commit to always use the surface we get back from AcquireNextFrame() and never hold it beyond the snapshot() call.
|
@psyke83 I wasn't able to reproduce that issue locally, but I think I understand the cause. Can you try the latest commit? |
6262281 to
761375e
Compare
|
This is better but issues are still not fully corrected. With the hw encoder: stream no longer closes, but the cursor ghosting issue remains present. Log shows no errors during black screen: I won't be able to troubleshoot further for a few more hours. |
|
Thanks for testing. Can you post a screenshot of the cursor ghosting issue? I'm not sure that I understand exactly what you mean by that. Is it like pointer trails are enabled and never go away, or something else? |
|
This is the cursor issue (which happens only on the hardware encoder): Screencast.from.2022-12-30.19-59-21.webmThe cursor issue can't be reproduced in GravityMark without this PR. This is the log without this PR applied: The new log shows the capture format also as |
761375e to
9a0d46b
Compare
With the D3D11 debug runtime loaded, the logs are full of: D3D11 ERROR: ID3D11DeviceContext::CopyResource: Cannot invoke CopyResource while a Subresource of the destination is mapped.Destination subresource (0) is mapped. [ RESOURCE_MANIPULATION ERROR LizardByte#285: COPYRESOURCE_INVALIDDESTINATIONSTATE] D3D11 ERROR: ID3D11DeviceContext::CopyResource: Cannot invoke CopyResource while a Subresource of the source is mapped.Source subresource (0) is mapped. [ RESOURCE_MANIPULATION ERROR LizardByte#286: COPYRESOURCE_INVALIDSOURCESTATE]
…SetRenderTargets and PSSetShaderResources The img texture is already bound as an input parameter from hwdevice_t::convert(), so it triggers a debug runtime warning to bind it again as a render target
|
@psyke83 ok, this PR is ready for one more test. I enabled the D3D11 debug runtime (D3D11_CREATE_DEVICE_DEBUG) and found a ton of bugs in both There also turned out to be a case where There is one case that is still broken on my Intel system with software encoding where |
|
This looks very promising so far. With the hardware encoder, I can confirm that the cursor ghosting issue is definitely resolved, and initial testing doesn't show any obvious issues. I think I should take some more time to test more generally, and not just focus on the Vulkan fullscreen issue. Software encoding is definitely improved, but I think the issue may not be 100% resolved. I am not experiencing any stream closes, and GravityMark's demo now renders correctly, but it's still possible to trigger a black screen that now occurs only on GravityMark's "Initializing" screen. When connected to the host via a VNC client at the same time, I can confirm that the "Initializing" image is rendering properly while Sunshine is showing a black screen + cursor. Here's a sample log when the black screen issue manifests: https://gist.github.com/psyke83/52f967939ab6ed3fb03999673cc228cd It seems from the log that a capture format change to Could this issue be related to the software encoder using a different (async) capture method? See here and here. As a troubleshooting measure, I tried removing the Edit: example video showing the black screen during "Initializing" on the software encoder: Screencast.from.2022-12-31.11-45-35.webm |
|
Speaking of Apologies if I'm polluting the PR, but it seems at least tangentially related given that these modes weren't working in the past. |
The format of the texture can change until then (and even return formats not provided in the array passed to DuplicateOutput1())
It might be a bug with
Yeah, the capture and encode threads race with each other using the I think we can support |
|
I didn't mean to try and expand the scope of this PR with talk of As of the latest commit you pushed, everything seems to be working perfectly with both |
Description
The first commit in this PR implements support for detection of DXGI format at the time
AcquireNextFrame()is called rather than duringdisplay::init(). This required reworking a lot of logic around the initialization ofimg_tobjects to separate format-dependent and format-independent attributes and handle creating dummy images where we don't know the capture format yet. I also did a little bit of P010 format prep work while I was in there.The second commit is a cherry-pick of @psyke83 's IDXGIOutput5 implementation which now works properly with the dynamic capture format support implemented in the first commit.
The third commit implements support for the
display_ram_tanddisplay_vram_tbackends to influence the selected capture formats.display_vram_tis pretty flexible (it even works withDXGI_FORMAT_R16G16B16A16_FLOAT), butdisplay_ram_thas some specific pixel format requirements due to the code that handles blending the cursor into the final image. In this commit, I also opteddisplay_vram_tintoDXGI_FORMAT_R8G8B8A8_UNORMsupport to hopefully improve capture performance for Vulkan and full-screen DX11 apps.Note for future testing: It is possible to request a specific format for testing by returning a single entry from
get_supported_sdr_capture_formats(). This allows testing things likeDXGI_FORMAT_R16G16B16A16_FLOATeven without HDR enabled. DWM will convert the desktop surface to the requested format.@psyke83 : I'd appreciate your review and testing before merging if you have time, since you did a lot of this initial work on IDXGIOutput5.
Screenshot
HEVC Main 10 works with NVENC (though video is still SDR):

Issues Fixed or Closed
Type of Change
.github/...)Checklist
Branch Updates
LizardByte requires that branches be up-to-date before merging. This means that after any PR is merged, this branch
must be updated before it can be merged. You must also
Allow edits from maintainers.