Skip to content

Conversation

cgutman
Copy link
Collaborator

@cgutman cgutman commented Jan 1, 2023

Description

I think I finally figured out what's going on with the unexpected capture format changes. It looks like DWM will cheat by using a surface that is in the desktop format until a frame is returned that that has LastPresentTime != 0 (which requires the DWM to convert the surface into the format we asked for).

Due to this behavior, #654 introduced a bug that would cause the surface format to constantly flip-flop between the requested capture format (when the desktop is updated) and the desktop format (when returning a cursor-only update). This format-switching happened constantly when requesting DXGI_FORMAT_R10G10B10A2_UNORM which led to very poor performance due to constantly reinitializing the capture session. This issue wasn't visible when we tested #654 because display_vram reported support for both R8G8B8A8 and B8G8R8A8 desktop formats, so the desktop format always matched the capture format.

To address this, I've added an intermediate texture (similar to the staging texture display_ram uses) to store a copy of the last captured desktop frame. If LastPresentTime == 0, we copy from that frame instead of src.

Screenshot

Issues Fixed or Closed

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Dependency update (updates to dependencies)
  • Documentation update (changes to documentation)
  • Repository update (changes to repository files, e.g. .github/...)

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated the in code docstring/documentation-blocks for new or existing methods/components

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.

  • I want maintainers to keep my branch updated

@psyke83
Copy link
Contributor

psyke83 commented Jan 1, 2023

This commit as-is doesn't seem to cause any noticeable problems with my AMD card & SDR only setup, but it has a bad interaction when tested together with #660 (so feel free to disregard in case you are aware) using the amdvce encoder (software seems ok):

When connecting to the host with no significant movement on-screen, the first frame received will look OK, but moving the mouse will trigger a full black frame to display and then the desktop image again, which repeats with each successive mouse movement for perhaps 3-5 seconds, and then the video will appear to stabilize with no further black frames being inserted. There is no log activity when this happens.

Edit: I also attempted to enable debugging via the D3D11_CREATE_DEVICE_DEBUG flag, but it causes Sunshine to exit with nothing logged when the first black frame displays (but I'm not an expert with DX debugging, so I'm not sure if I need to look elsewhere for the debug logs or run in a debugger).

@cgutman
Copy link
Collaborator Author

cgutman commented Jan 1, 2023

Ok, thanks for testing. I think I'm going to take a different approach with #660 and try using 2 separate ID3D11Device objects (one for capture and one for encode) then pass textures between them using D3D11_RESOURCE_MISC_SHARED_NTHANDLE and ID3D11Device1::OpenSharedResource1().

Edit: I also attempted to enable debugging via the D3D11_CREATE_DEVICE_DEBUG flag, but it causes Sunshine to exit with nothing logged when the first black frame displays (but I'm not an expert with DX debugging, so I'm not sure if I need to look elsewhere for the debug logs or run in a debugger).

Yeah, I think certain fatal errors (like synchronization issues) will cause the debug runtime to raise an exception that will kill the process without a debugger attached. If you attach to sunshine.exe with WinDbg, it will show you debug messages from the debug runtime.

@cgutman cgutman force-pushed the format_switch_fix branch 2 times, most recently from 189d441 to 9c419ff Compare January 1, 2023 22:36
@cgutman
Copy link
Collaborator Author

cgutman commented Jan 1, 2023

While I was redoing #660, I figured out what the problem was and it was indeed a bug in this PR, though one that's only likely to show up with PARALLEL_ENCODING because DEFAULT only uses a single image. I forgot to call complete_img() in the newly added codepath, so we'd pass back an image with no texture inside if this was the first capture using that image.

@cgutman
Copy link
Collaborator Author

cgutman commented Jan 2, 2023

I pushed an additional fix for an issue in #654 that I discovered when testing my parallel encoding work. We don't actually want to fall back to DuplicateOutput() if DuplicateOutput1() is available.

There are temporary reasons that desktop duplication fails (such as being in the middle of a modeset operation or the secure desktop being displayed when not running as service). If we happen to fail our 2 tries of DuplicateOutput1() and succeed in the call to DuplicateOutput(), then we'll be stuck with suboptimal capture performance until something else triggers the capture to reinitialize.

@ReenigneArcher ReenigneArcher merged commit 76ffa2a into LizardByte:nightly Jan 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants