SpecialK icon indicating copy to clipboard operation
SpecialK copied to clipboard

[dgVoodoo v2.78] HDR retrofit needs resolution override to work

Open mirh opened this issue 2 years ago • 14 comments

Set up everything with the instructions here and version 2.77 and it works. Replace the d3d9.dll with 2.78, and you get a black screen (SDR has no problems). Tested on W10 21H2 with a 3060 and forceware 512.15.

Then, for all I know it may not even be a problem with SK (22.5.30), but Dege didn't particularly seem to care about this niche case, so...

mirh avatar Jun 11 '22 16:06 mirh

Sounds a lot like he needs to turn on flip model for the D3D11 renderer. That's the only way HDR will work. I'm guessing there was some kind of regression between 2.77 and 2.78?

Kaldaien avatar Jun 11 '22 18:06 Kaldaien

I believe the same issue actually occurs with the WIP86.1 version as well, which he added support for flip override to:

https://www.vogons.org/viewtopic.php?p=1070127#p1070127

Aemony avatar Jun 11 '22 19:06 Aemony

Uh, I had missed the beta builds. I can confirm the breakage happened somewhere between WIP83_1 and WIP84.

I don't think this has anything to do with the flip model though. SK was already handling the switch good, and even now that it doesn't work anymore the reported display/framebuffer/presentation properties are still the same. Also, forcing flip presentation modes from the nightly in the last link doesn't change anything (except the fact that now, even if I already have my monitor in HDR mode, I still have 5s resolution switch.. to the same HDR mode I was already using).

mirh avatar Jun 12 '22 00:06 mirh

Have you tried one of the more recent builds? I resolved a few issues that might be related to this; mostly MSAA.

Kaldaien avatar Jun 15 '22 13:06 Kaldaien

Still the same with 22.6.16.

mirh avatar Jun 16 '22 13:06 mirh

Someone else on the Discord mentiomed having the same issue, but only on Windows 11 weirdly enough.

For them Windows 10 worked as intended.

Aemony avatar Jun 25 '22 11:06 Aemony

Maybe it depends on the driver version? Or some other magic like hardware accelerated GPU scheduling

mirh avatar Jun 25 '22 13:06 mirh

I think I've heard of this affecting more games than just Mass Effect, so changing the title to reflect that. No idea still what's causing this though, but from the fact that it started happening between dgVoodoo WIP83_1 and WIP84 suggests that dgVoodoo of today does not behave as expected by Special K.

A few years ago Kal improved compatibility with dgVoodoo in Special K, and it was around this time SK started being able to show the "7->11" text label that it now shows when dgVoodoo is being used. It possible that some of that code isn't up-to-date with dgVoodoo's current behaviour, I guess?

Aemony avatar Jul 23 '22 08:07 Aemony

Hi all,

I remember mirh reporting this issue earlier, but I forgot about it. Anyways, between WIP83.1 and WIP84 I modified the image presentation in dgVoodoo. I optimized it for better perfomance.

  • Till WIP83.1 the final image was composed in a temporary texture and that was copied into the swapchain backbuffer. Either by raw copy or shader copy, depending on the circumstances and the additional postprocessing (color adjusments, etc) needs.

  • Starting with WIP84 the step for the intermediate texture is skipped, the final image is drawn directly into the swapchain backbuffer with raw (sub)resource copies when possible.

Can the raw-copy be the cause? Because I guess that the swapchain backbuffer format is silently overridden in the background for auto HDR but that's not compatible with the raw copying (src and dst formats are different) and the HDR hook cannot do anything than fall back to the original backbuffer format (or simply does nothing). With shader copy, this problem does not arise. But it's only a tip on my part.

dege-diosg avatar Jul 24 '22 19:07 dege-diosg

Actually, Special K should be able to handle these scenarios. It already does something similar to your copy-to-SwapChain when the original and override formats aren't directly compatible (e.g. sRGB <--> FP16). I have a shader that'll draw a textured quad to basically emulate StretchRect.

The biggest problem with SK / dgVoodoo compatibility seems to be code that's destroying and then creating a new SwapChain every frame. I don't know if that's intentional, but it's complicated to handle. SK has to do a lot of re-initialization every time a SwapChain is destroyed.

Kaldaien avatar Jul 24 '22 20:07 Kaldaien

The swapchain isn't recreated every frame, that'd be a crazy overhead. Maybe an AddRef/Release somewhere on the DXGI swapchain object during the presentation, I can't remember, but the refcnt shouldn't decrease to 0, so it shouldn't be destroyed. Only when the wrapped app destroys the frontend swapchain object.

dege-diosg avatar Jul 24 '22 20:07 dege-diosg

I tried multiple releases, and for D3D9 games they are all doing this:

SpecialK.log

Once per-frame, it makes a redundant call to SetFullscreenState (...) to switch to windowed mode (it's already windowed mode, even without SK's overrides). After that redundant call, it destroys the existing SwapChain and then attempts to create a new SwapChain.

This had extreme performance overhead before I implemented DXGI SwapChain / HWND recycling. Now I just return the original SwapChain to dgVoodoo when it tries to do this and D3D9 games run at playable framerates, but unfortunately flood SK's logs with all this SwapChain recreation activity.

Kaldaien avatar Jul 24 '22 22:07 Kaldaien

What is called every frame is GetFullscreenState to get aware if DXGI watchdog thread kicked the swapchain out from fullscreen state because of any reason. But even when the swapchain turns out not to be in the expected state, only its buffers are resized, the swapchain itself isn't recreated. There is another case, when the wrapped application changes resolution. Then dgVoodoo calls swapchain GetDesc to see if the current properties like the scaling, refresh rate rational and such match the new expected values. If not then then the swapchain is indeed recreated. The old one is set into windowed mode before that because a swapchain should be released in windowed state according to MS docs.

Does it occur generally with any app wrapped with dgVoodoo? I've just given a try to a D3D9 game (wrapped to D3D11), placed a breakpoint into DXGI adapter CreateSwapchain but it was called only at startup and when I experimentally changed resolution from the game menu. I really don't understand this issue because if the swapchain were released every frame then the application couldn't even run, the game rendering window would be switching back and forth between windowed/full screen state, making the wrapping completely unusable.

dege-diosg avatar Jul 25 '22 08:07 dege-diosg

Well, holy shit. I was trying to pin down why WIP89_1 was outright crashing on start (not even just a black screen for more than half a second)... Then (of course) every time I try to revert to a known working configuration, that's broken on the first try and I better wipe SK.ini. And last but not least in-between I also found a situation where the game was running (and I could hear sound) but there was no game window.

So while bisecting the .inis I started to tinker with OverrideRes (which I believe gets automatically set if you do ALT+⏎ENTER)... and boom, WIP89_1 that I had forgotten still ready-to-be-loaded in the folder began to work. And the craziest thing is that I had also forgotten to set any other compatibility option in the fresh ini (including Promote8BitRTsTo16) but it was still all nice and dandy. Instructions are now updated on PCGW and (while I guess there's still room for improvement) boy aren't they sleeker.

I suspect this may also relate to the fact that changing resolution in-game (or even just using the fullscreen toggle checkbox) is recipe for instant crashes.

mirh avatar Jan 11 '23 16:01 mirh