Skip to content

DX11 DWM vsync fix for windowed modes + fix for broken blur passes + TODO with explanation of issue for MSAA w/ volumetrics error#72

Merged
themrdemonized merged 4 commits intothemrdemonized:all-in-one-vs2022-wpofrom
deggua:dx11-refresh-fix
Sep 15, 2024
Merged

DX11 DWM vsync fix for windowed modes + fix for broken blur passes + TODO with explanation of issue for MSAA w/ volumetrics error#72
themrdemonized merged 4 commits intothemrdemonized:all-in-one-vs2022-wpofrom
deggua:dx11-refresh-fix

Conversation

@deggua
Copy link
Contributor

@deggua deggua commented Sep 15, 2024

Sorry for bundling all this in one PR, I tried to break up the commits to make it easier to see what changes are relevant for each issue. Also sorry for trailing whitespace changes, but probably better they're gone now :)

DX11 DWM vsync issue:

  • By default, windowed mode applications in FLIP presentation modes vsync to the DWM, so if your desktop refresh rate was 60Hz and the game was in a windowed mode (borderless/windowed) the renderer would be locked to 60Hz even if it could run at a higher framerate (even with the in-game vsync disabled)
  • DX11 has a way to turn this off, but is a relatively new feature, so some configurations may not support it. It also requires some swapchain flags to enable, and a flag to the Present call
  • Now, by default (if vsync is disabled) we try to enable this option DXGI_PRESENT_ALLOW_TEARING to unlock the framerate in windowed modes
  • Still has an issue on my PC in particular, I put a TODO in to figure out why since it works for you without issue. For anyone reading this in the future, the issue is that if I launch the game in a windowed mode it's still vsync'd by the DWM, but if I switch into exclusive fullscreen then back to windowed/borderless it is no longer vsync'd
    • PresentMon provided no useful insight into why, but could be useful in the future for similar issues

New DXGI debug argument:

  • I added --dxgi-dbg to enable the D3D debug layer without requiring recompilation (currently only for DX11)
  • This lets the graphics API tell you if you're doing something (it uses OutputDebugString so you either need to run the game in a debugger that displays that output, or use a tool like DebugView) wrong and can help a lot with debugging
  • Best way I've found to use it is to:
    1. Launch the game in RenderDoc with --dxgi-dbg as an argument, with Enable API Validation and Collect Callstacks enabled
    2. Take a capture of a frame, open the capture
    3. Go to Tools > Load Symbols to load debug symbols for callstack view
    4. Look at the API validation errors in RenderDoc, it will show you the Render Event where the issue occurred and the callstack that the render call came from (helps a lot with finding where the broken thing is in the code)
  • Some issues, like the weirdness with ResizeBuffers don't happen within a frame so you'll just have to look at the debug output log

Fixing broken blur render passes:

  • Using the process described above, I found that the blur passes were broken because they were trying to use a color target with a different resolution than the associated depth target
  • Fixed this by creating separate depth targets for DX9/DX10/DX11
  • Not actually sure that these passes require a depth/stencil buffer, in which case we could save some VRAM by not creating these targets and passing NULL for the depth buffer argument to u_setrt to disable binding one

MSAA volumetrics error:

  • Similarly, with the debug layer, I found that when MSAA is enabled in DX11 we're trying to use a multisampled color target (rt_Generic_2) with a non-multisampled depth buffer (HW.pBaseZB) which is a hard API error
  • I put a TODO in because I'm not really sure what the right fix is, since it can use NULL if RImplementation.o.ssfx_volumetric is enabled, so maybe we could just pass NULL? Otherwise I think we would use rt_MSAADepth->pZRT or a new depth target, but this might require a multisample resolve

- Added `--dxgi-dbg` argument to enable the D3D debug layer without requiring recompilation
- Fixed issue with windowed/fullscreen transitions when display mode is changed
…epth buffer resolution (HW.pBaseRT is the fullscreen depth buffer, but the blur passes use 1/2, 1/4, and 1/8 resolution color targets which is an API use error)

- DX9 doesn't have `rt->pZRT` like DX10/11 so has to directly create a depth stencil surface for Z-buffers (which requires appropriate cleanup in the destructor)
- I'm not sure that these passes need depth buffers, but the original code was trying to use them. If not required could save a little bit of VRAM and just pass 0/NULL to those functions
@themrdemonized themrdemonized merged commit 4668344 into themrdemonized:all-in-one-vs2022-wpo Sep 15, 2024
themrdemonized added a commit that referenced this pull request Sep 15, 2024
DX11 DWM vsync fix for windowed modes + fix for broken blur passes + TODO with explanation of issue for MSAA w/ volumetrics error

(cherry picked from commit 4668344)
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.

2 participants