- Status
- Offline
- Joined
- Mar 3, 2026
- Messages
- 271
- Reaction score
- 7
Had a persistent issue with my internal hook where Alt-Tabbing in fullscreen exclusive mode would nuke the game's gamma settings and force a weird resolution stretch. It was brutal—mat_monitorgamma would essentially stop responding, and the buffer would try to force a 1080p state on tab-out, which is a classic symptom of the device parameters fighting the game's own swap chain state.
The problematic initialization logic looked something like this:
The Hook Context:
Observations:
Has anyone else seen this specific behavior when using inline hooks on Direct3D devices, or is there a specific flag in the D3DPRESENT_PARAMETERS that usually triggers this kind of swap chain conflict?
The problematic initialization logic looked something like this:
Code:
void hooks::d3d9::init() {
com_ptr<IDirect3D9> d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
auto window = FindWindowA("Source001", nullptr);
D3DPRESENT_PARAMETERS params{
.BackBufferFormat = D3DFMT_UNKNOWN,
.SwapEffect = D3DSWAPEFFECT_DISCARD,
.Windowed = TRUE,
.EnableAutoDepthStencil = TRUE,
.AutoDepthStencilFormat = D3DFMT_D16,
.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT,
};
// ... device creation ...
}
The Hook Context:
Code:
long present_hook::hook(IDirect3DDevice9* device, RECT* src_rect, RECT* dest_rect, HWND dest_wnd_override, RGNDATA* dirty_region) {
return original(device, src_rect, dest_rect, dest_wnd_override, dirty_region);
}
Observations:
- The glitch wasn't captured in OBS, pointing directly to the interaction between the D3D9 device hook and the game's own display state management.
- The resolution snap on the last frame before the window loses focus suggested that my overlay's Present parameters were clashing with the exclusive fullscreen state.
- A full rewrite of the hook logic fixed the immediate issue, but the root cause of why the previous parameters were forcing that specific behavior remains elusive.
If your overlay is fighting your monitor gamma or resolution on tab-out, look at how you're handling the device pointer and whether your Present parameters are accidentally overriding the game's default swap chain behavior. In many Source engine titles, especially when forced into exclusive mode, improper parameters will cause the device to attempt a reset to your defined state rather than following the game's internal resolution management.
Has anyone else seen this specific behavior when using inline hooks on Direct3D devices, or is there a specific flag in the D3DPRESENT_PARAMETERS that usually triggers this kind of swap chain conflict?