Nonary / MonitorSwapAutomation

Automates swapping to a dummy plug when streaming, then automates swapping back to primary monitor once finished.
302 stars 9 forks source link

The script doesnt work half the time #46

Closed Mrsalai closed 2 months ago

Mrsalai commented 3 months ago

So basically about 5/10 occasions the script doesnt function And I get a no encode device error. After restarting sunshine it works again. I tried changing strict restore, start delay and I did not set any forced codec ,gpu or monitor.

Nonary commented 3 months ago

Are you using a virtual display driver like IDDSampleDriver?

Mrsalai commented 3 months ago

Yep

Nonary commented 3 months ago

Yep

There is a bug currently in Sunshine where it will pick the iGPU instead of the dedicated GPU causing it to display errors like no video from host or encoding errors.

https://github.com/LizardByte/Sunshine/pull/3002

Try installing this version of sunshine which contains the fix https://github.com/LizardByte/Sunshine/actions/runs/10430297817/artifacts/1822589139

Mrsalai commented 3 months ago

Is this the nightly version or just patched sunshine?

Nonary commented 3 months ago

Is this the nightly version or just patched sunshine?

It's not yet in the nightly version of sunshine, the link I provided you is the patched version from the pull request

Mrsalai commented 3 months ago

Got it thanks, I will reply in a few days if it fixed it or not.

Nonary commented 3 months ago

Got it thanks, I will reply in a few days if it fixed it or not.

Did it resolve the issue?

Mrsalai commented 3 months ago

Yes, its fixed, I hope they will accept your edit into the main build.

broslife commented 2 months ago

@Nonary Hi. I tried to use the Sunshine version you've provided above but still I can't get the script to work properly. I also have hybrid mode enabled in my laptop and when I try to start streaming I get error code -1

[2024-09-01 10:57:35.360]: Info: Executing Do Cmd: [powershell.exe -executionpolicy bypass -file "C:\Apps\MonitorSwapper\StreamMonitor.ps1" -n MonitorSwapper]
[2024-09-01 10:57:35.368]: Info: powershell.exe -executionpolicy bypass -file "C:\Apps\MonitorSwapper\StreamMonitor.ps1" -n MonitorSwapper running with PID 804
[2024-09-01 10:57:39.709]: Info: Executing [Desktop]
[2024-09-01 10:57:40.159]: Info: nvprefs: No need to modify application profile settings
[2024-09-01 10:57:40.160]: Info: nvprefs: No need to modify global profile settings
[2024-09-01 10:57:40.308]: Info: CLIENT CONNECTED
[2024-09-01 10:57:40.390]: Info: Changed virtual audio sink format to [S32 48000 2.0]
[2024-09-01 10:57:40.456]: Info: Audio capture format is [F32 48000 2.0]
[2024-09-01 10:57:40.457]: Info: Opus initialized: 48 kHz, 2 channels, 512 kbps (total), LOWDELAY
[2024-09-01 10:57:40.779]: Error: DuplicateOutput() test failed [0x887A0004]
[2024-09-01 10:57:41.333]: Error: Failed to locate an output device
[2024-09-01 10:57:41.834]: Error: Failed to locate an output device

The automation seems to work, but the streaming don't. I have dual monitors (laptop and a second monitor) and configured MonitorSwapAutomation to only use my second monitor when start streaming. I can see my second monitor being enabled and my laptop's monitor being disable, but then I get this error code "-1". Same thing when I try to use MonitorProfileSwitcher.

Do you have any ideas?

Nonary commented 2 months ago

@Nonary Hi. I tried to use the Sunshine version you've provided above but still I can't get the script to work properly. I also have hybrid mode enabled in my laptop and when I try to start streaming I get error code -1


[2024-09-01 10:57:35.360]: Info: Executing Do Cmd: [powershell.exe -executionpolicy bypass -file "C:\Apps\MonitorSwapper\StreamMonitor.ps1" -n MonitorSwapper]

[2024-09-01 10:57:35.368]: Info: powershell.exe -executionpolicy bypass -file "C:\Apps\MonitorSwapper\StreamMonitor.ps1" -n MonitorSwapper running with PID 804

[2024-09-01 10:57:39.709]: Info: Executing [Desktop]

[2024-09-01 10:57:40.159]: Info: nvprefs: No need to modify application profile settings

[2024-09-01 10:57:40.160]: Info: nvprefs: No need to modify global profile settings

[2024-09-01 10:57:40.308]: Info: CLIENT CONNECTED

[2024-09-01 10:57:40.390]: Info: Changed virtual audio sink format to [S32 48000 2.0]

[2024-09-01 10:57:40.456]: Info: Audio capture format is [F32 48000 2.0]

[2024-09-01 10:57:40.457]: Info: Opus initialized: 48 kHz, 2 channels, 512 kbps (total), LOWDELAY

[2024-09-01 10:57:40.779]: Error: DuplicateOutput() test failed [0x887A0004]

[2024-09-01 10:57:41.333]: Error: Failed to locate an output device

[2024-09-01 10:57:41.834]: Error: Failed to locate an output device

The automation seems to work, but the streaming don't. I have dual monitors (laptop and a second one) and configured MonitorSwapAutomation to only use my second monitor when start streaming. I can see my second monitor being enabled and my laptop's monitor being disable, but then I can this error code-1. Same thing when I try to use MonitorProfileSwitcher.

Do you have any ideas?

I need the entire logs of sunshine, plus the logs of the monitor swapper. Keep in mind sunshine erases logs every time it is restarted so you'll have to repeat the issue if you've stopped sunshine and started it recently

broslife commented 2 months ago

I need the entire logs of sunshine, plus the logs of the monitor swapper. Keep in mind sunshine erases logs every time it is restarted so you'll have to repeat the issue if you've stopped sunshine and started it recently

Thank you very much for your replay.

Here you can get the entire sunshine's logs: sunshine_log.txt

Here you'll find the MonitorSwap's logs: log_1725211415.txt

Again, I did not configure any dummy display. My goal is to automatically use only my second monitor when I start streaming. That way, I can turn off the screen of my second monitor, and my laptop's screen will also be turned off because the script is supposed to enable only the second monitor. I followed your guide, but targeted my second monitor instead of a dummy device/virtual display. I also set the resolution and refresh rate in the dummy.cfg file to my desired settings.

Nonary commented 2 months ago

I need the entire logs of sunshine, plus the logs of the monitor swapper. Keep in mind sunshine erases logs every time it is restarted so you'll have to repeat the issue if you've stopped sunshine and started it recently

Thank you very much for your replay.

Here you can get the entire sunshine's logs: sunshine_log.txt

Here you'll find the MonitorSwap's logs: log_1725211415.txt

Again, I did not configure any dummy display. My goal is to automatically use only my second monitor when I start streaming. That way, I can turn off the screen of my second monitor, and my laptop's screen will also be turned off because the script is supposed to enable only the second monitor. I followed your guide, but targeted my second monitor instead of a dummy device/virtual display. I also set the resolution and refresh rate in the dummy.cfg file to my desired settings.

Can you move the script to your user profile instead of C:\Apps?

It generally does not work properly outside of user profile due to how Windows handles read/write access.

Nonary commented 2 months ago

Is it a virtual or actual dummy plug? if its virtual, you need to use https://github.com/itsmikethetech/Virtual-Display-Driver/releases/tag/24.8.6 as this version is designed to always attach to dedicated GPU

Don't include the xml file, just remove and reinstall driver, again only matters if youre using virtual display instead of dummy plug

broslife commented 2 months ago

Can you move the script to your user profile instead of C:\Apps? It generally does not work properly outside of user profile due to how Windows handles read/write access.

I just tried and did not work, same error code "-1" and same log description.

Is it a virtual or actual dummy plug? if its virtual, you need to use https://github.com/itsmikethetech/Virtual-Display-Driver/releases/tag/24.8.6 as this version is designed to always attach to dedicated GPU

It's not either a dummy plug or virtual display. I did not want to mess with virtual display, since I got issues last time about my entire screen getting black even after restarting laptop. Somehow the virtual display got activated as primary display and had little headache to get things back.

My laptop only has a one HDMI port which I use to connect my second monitor and I used it as extended mode. This is my normal/daily setup. What I want is just automate the process of disable my laptop's monitor and only enable my second monitor. That way I can just turn off my second monitor's screen while it still plugged and powered on. What I did was configure the dummy.cfg to use only my second monitor instead a virtual/dummy display.

One curios thing is:

After do these steps, if I start streaming again from moonlight everything works as supposed to. Somehow if I first start streaming with the dummy.cfg condition already enabled and then get the primary.cfg condition back again, if start streaming again from primary.cfg condition enabled everything works. However if I restart sunshine then it stops to work again and I receive the error code "-1".

Nonary commented 2 months ago

Can you move the script to your user profile instead of C:\Apps? It generally does not work properly outside of user profile due to how Windows handles read/write access.

I just tried and did not work, same error code "-1" and same log description.

Is it a virtual or actual dummy plug? if its virtual, you need to use https://github.com/itsmikethetech/Virtual-Display-Driver/releases/tag/24.8.6 as this version is designed to always attach to dedicated GPU

It's not either a dummy plug or virtual display. I did not want to mess with virtual display, since I got issues last time about my entire screen getting black even after restarting laptop. Somehow the virtual display got activated as primary display and had little headache to get things back.

My laptop only has a one HDMI port which I use to connect my second monitor and I used it as extended mode. This is my normal/daily setup. What I want is just automate the process of disable my laptop's monitor and only enable my second monitor. That way I can just turn off my second monitor's screen while it still plugged and powered on. What I did was configure the dummy.cfg to use only my second monitor instead a virtual/dummy display.

One curios thing is:

  • I activate the dummy.cfg before start streaming through moonlight (which means it enables only my second monitor and disables my laptop's monitor)
  • Restart Sunshine
  • Start the streaming through moonlight. (it works properly and no error code)
  • Stop streaming session through moonlight (the primary.cfg script activates and my laptop's monitor gets enabled again in extended mode)

After do these steps, if I start streaming again from moonlight everything works as supposed to. Somehow if I first start streaming with the dummy.cfg condition already enabled and then get the primary.cfg condition back again, if start streaming again from primary.cfg condition enabled everything works. However if I restart sunshine then it stops to work again and I receive the error code "-1".

Unfortunately, I can't fix that issue because it's a limitation of DXGI itself. The problem happens because the laptop switches between integrated and hybrid graphics. If Sunshine is set to use dedicated graphics while the display is set to integrated graphics (or vice versa), it won't be able to capture properly. Additionally, Microsoft has a restriction where the GPU preference can only be set once per process's lifetime. That's why you're noticing it works only once before you need to restart the process.

I'll ask the Sunshine developer community about the possibility of allowing Sunshine to restart itself if it encounters a DXGI failure. This could work around the "once per lifetime" issue by automating the restart process. But beyond that, there's no solution until Microsoft changes the API to allow setting GPU preference more than once per process lifetime.

broslife commented 2 months ago

Unfortunately, I can't fix that issue because it's a limitation of DXGI itself. The problem happens because the laptop switches between integrated and hybrid graphics. If Sunshine is set to use dedicated graphics while the display is set to integrated graphics (or vice versa), it won't be able to capture properly. Additionally, Microsoft has a restriction where the GPU preference can only be set once per process's lifetime. That's why you're noticing it works only once before you need to restart the process.

I'll ask the Sunshine developer community about the possibility of allowing Sunshine to restart itself if it encounters a DXGI failure. This could work around the "once per lifetime" issue by automating the restart process. But beyond that, there's no solution until Microsoft changes the API to allow setting GPU preference more than once per process lifetime.

Okay, I got it. Thank you very much for your explanation and your time.

I think even if I try to use a virtual display, instead of enabling only my second monitor as I'm doing, will I face the same issue, right? Since the problem it seems to be related to the hybrid mode (iGPU and dGPU activated at the same time).

Nonary commented 2 months ago

Unfortunately, I can't fix that issue because it's a limitation of DXGI itself. The problem happens because the laptop switches between integrated and hybrid graphics. If Sunshine is set to use dedicated graphics while the display is set to integrated graphics (or vice versa), it won't be able to capture properly. Additionally, Microsoft has a restriction where the GPU preference can only be set once per process's lifetime. That's why you're noticing it works only once before you need to restart the process. I'll ask the Sunshine developer community about the possibility of allowing Sunshine to restart itself if it encounters a DXGI failure. This could work around the "once per lifetime" issue by automating the restart process. But beyond that, there's no solution until Microsoft changes the API to allow setting GPU preference more than once per process lifetime.

Okay, I got it. Thank you very much for your explanation and your time.

I think even if I try to use a virtual display, instead of enabling only my second monitor as I'm doing, will I face the same issue, right? Since the problem it seems to be related to the hybrid mode (iGPU and dGPU activated at the same time).

You should only need to restart it if Sunshine was launched while in extended mode. However, I'm not completely sure—it might require a restart any time you need to stream. After reviewing the code, it seems this issue can't be fixed in Sunshine without altering the streaming method to resemble GameStream, which spawns a new process for each session or connection.

This change would significantly increase code complexity, so unlikely to happen because of that.

broslife commented 2 months ago

You should only need to restart it if Sunshine was launched while in extended mode. However, I'm not completely sure—it might require a restart any time you need to stream. After reviewing the code, it seems this issue can't be fixed in Sunshine without altering the streaming method to resemble GameStream, which spawns a new process for each session or connection. This change would significantly increase code complexity, so unlikely to happen because of that.

Got it. I would need an automation to disable extended mode every time I want to stream. I would actually need to disable extended mode and restart sunshine to work properly. Indeed it seems too much complicated. But thank you anyway.

Nonary commented 2 months ago

Closing out issue as original poster confirmed that the sunshine fix resolved their issue

Nonary commented 2 months ago

@broslife I have some good news, I am currently developing a workaround script to the DuplicateOutput Failed Issue and the issue with laptops with hybrid GUIs. I was able to replicate the issue on my desktop and develop a proof of concept: https://github.com/Nonary/DuplicateOutputFailFix

broslife commented 2 months ago

@broslife I have some good news, I am currently developing a workaround script to the DuplicateOutput Failed Issue and the issue with laptops with hybrid GUIs. I was able to replicate the issue on my desktop and develop a proof of concept: https://github.com/Nonary/DuplicateOutputFailFix

Hi! Thanks for let me know. I will be glad to test your proof of concept and then share the results with you.

broslife commented 2 months ago

@Nonary

I tested your PoC following all the steps you from the guide and it worked very well.

One question about the HybridGPUMonitorTask. Is this script running constantly? It doesn't affect nothing about computer's performance?

Nonary commented 2 months ago

@Nonary

I tested your PoC following all the steps you from the guide and it worked very well.

One question about the HybridGPUMonitorTask. Is this script running constantly? It doesn't affect nothing about computer's performance?

It does run in the background, in order for the script to work properly it has to monitor the log file of Sunshine at all times.

I have optimized it to only poll once a second, and the entire log is streamed and buffered so it doesn't load the entire file in memory at once. Both of these optimizations keeps the CPU usage and RAM low.

Nonary commented 2 months ago

On my system it is taking 0% CPU usage and consumes a paltry 19MB of memory for example

broslife commented 2 months ago

Sometimes, when I initiate the streaming I receive this message from moonlight:

Screenshot_20240927_073944_Moonlight

Them, I just press OK and then I try again and it works. Not sure what would be causing this.

Nonary commented 2 months ago

Sometimes, when I initiate the streaming I receive this message from moonlight:

Screenshot_20240927_073944_Moonlight

Them, I just press OK and then I try again and it works. Not sure what would be causing this.

The script automates restarting sunshine in the scenario where the GPU preference needs to change, which means there will be sometimes where you start a stream it will kick you back out to start streaming again because Sunshine had to be restarted.

There is no way around that, otherwise you wouldn’t be able to stream at all until you manually restarted Sunshine like discussed earlier in this issue.