From 11fbc5717890daffad08f16a50239fc4ae4fddad Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 22 Sep 2009 20:17:54 +0000 Subject: [PATCH] - Added a technique to try and minimize input lag with vsync enabled: Two surfaces are alternately locked for read-only access each frame, forcing the driver to stop buffering more than one frame at a time. The input lag on my system doesn't seem to be as bad as it once was (I can no longer see it obviously with my naked eye), but turning antilag on "feels" slightly more responsive. The cvar d3d_antilag turns this technique on and off. See for more details. SVN r1870 (trunk) --- docs/rh-log.txt | 9 ++++++ src/win32/fb_d3d9.cpp | 65 ++++++++++++++++++++++++++++++++++++------ src/win32/win32iface.h | 4 +++ 3 files changed, 70 insertions(+), 8 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 6b287c387..ac304a52d 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,12 @@ +September 22, 2009 +- Added a technique to try and minimize input lag with vsync enabled: Two + surfaces are alternately locked for read-only access each frame, forcing + the driver to stop buffering more than one frame at a time. The input lag + on my system doesn't seem to be as bad as it once was (I can no longer + see it obviously with my naked eye), but turning antilag on "feels" + slightly more responsive. The cvar d3d_antilag turns this technique on and + off. See for more details. + September 22, 2009 (Changes by Graf Zahl) - Added a check to Dehacked code which tries to set the blend color. It must set it to 0 if the alpha is 0 to avoid problems with special diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index 0cf47e9a6..562abf13d 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -246,6 +246,7 @@ CUSTOM_CVAR(Bool, vid_hw2d, true, CVAR_NOINITCALL) BorderNeedRefresh = SB_state = screen->GetPageCount(); } +CVAR(Bool, d3d_antilag, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR(Int, d3d_showpacks, 0, 0) CVAR(Bool, vid_hwaalines, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) @@ -276,6 +277,8 @@ D3DFB::D3DFB (int width, int height, bool fullscreen) { Shaders[i] = NULL; } + BlockSurface[0] = NULL; + BlockSurface[1] = NULL; FBFormat = D3DFMT_UNKNOWN; PalFormat = D3DFMT_UNKNOWN; VSync = vid_vsync; @@ -531,6 +534,7 @@ bool D3DFB::CreateResources() { return false; } + CreateBlockSurfaces(); return true; } @@ -640,6 +644,8 @@ void D3DFB::ReleaseDefaultPoolItems() SAFE_RELEASE( InitialWipeScreen ); SAFE_RELEASE( VertexBuffer ); SAFE_RELEASE( IndexBuffer ); + SAFE_RELEASE( BlockSurface[0] ); + SAFE_RELEASE( BlockSurface[1] ); } //========================================================================== @@ -674,10 +680,35 @@ bool D3DFB::Reset () { return false; } + CreateBlockSurfaces(); SetInitialState(); return true; } +//========================================================================== +// +// D3DFB :: CreateBlockSurfaces +// +// Create blocking surfaces for antilag. It's okay if these can't be +// created; antilag just won't work. +// +//========================================================================== + +void D3DFB::CreateBlockSurfaces() +{ + BlockNum = 0; + if (SUCCEEDED(D3DDevice->CreateOffscreenPlainSurface(16, 16, D3DFMT_A8R8G8B8, + D3DPOOL_DEFAULT, &BlockSurface[0], 0))) + { + if (FAILED(D3DDevice->CreateOffscreenPlainSurface(16, 16, D3DFMT_A8R8G8B8, + D3DPOOL_DEFAULT, &BlockSurface[1], 0))) + { + BlockSurface[0]->Release(); + BlockSurface[0] = NULL; + } + } +} + //========================================================================== // // D3DFB :: KillNativePals @@ -921,10 +952,7 @@ void D3DFB::Update () DrawRateStuff(); DrawPackedTextures(d3d_showpacks); EndBatch(); // Make sure all batched primitives are drawn. - DoWindowedGamma(); - D3DDevice->EndScene(); - D3DDevice->Present(NULL, NULL, NULL, NULL); - InScene = false; + Flip(); } In2D = 0; return; @@ -987,10 +1015,7 @@ void D3DFB::Update () Draw3DPart(In2D <= 1); if (In2D == 0) { - DoWindowedGamma(); - D3DDevice->EndScene(); - D3DDevice->Present(NULL, NULL, NULL, NULL); - InScene = false; + Flip(); } BlitCycles.Unclock(); @@ -1000,6 +1025,30 @@ void D3DFB::Update () UpdatePending = false; } +void D3DFB::Flip() +{ + assert(InScene); + + DoWindowedGamma(); + D3DDevice->EndScene(); + + // Attempt to counter input lag. + if (d3d_antilag && BlockSurface[0] != NULL) + { + D3DLOCKED_RECT lr; + volatile int dummy; + D3DDevice->ColorFill(BlockSurface[BlockNum], NULL, D3DCOLOR_ARGB(0xFF,0,0x20,0x50)); + BlockNum ^= 1; + if (!FAILED((BlockSurface[BlockNum]->LockRect(&lr, NULL, D3DLOCK_READONLY)))) + { + dummy = *(int *)lr.pBits; + BlockSurface[BlockNum]->UnlockRect(); + } + } + D3DDevice->Present(NULL, NULL, NULL, NULL); + InScene = false; +} + bool D3DFB::PaintToWindow () { HRESULT hr; diff --git a/src/win32/win32iface.h b/src/win32/win32iface.h index 785664abd..e4c21a015 100644 --- a/src/win32/win32iface.h +++ b/src/win32/win32iface.h @@ -226,6 +226,7 @@ public: bool Lock (bool buffered); void Unlock (); void Update (); + void Flip (); PalEntry *GetPalette (); void GetFlashedPalette (PalEntry palette[256]); void UpdatePalette (); @@ -332,6 +333,7 @@ private: bool CreateResources(); void ReleaseResources(); bool LoadShaders(); + void CreateBlockSurfaces(); bool CreateFBTexture(); bool CreatePaletteTexture(); bool CreateGrayPaletteTexture(); @@ -404,6 +406,7 @@ private: bool SM14; bool GatheringWipeScreen; bool AALines; + BYTE BlockNum; D3DPal *Palettes; D3DTex *Textures; PackingTexture *Packs; @@ -427,6 +430,7 @@ private: IDirect3DPixelShader9 *Shaders[NUM_SHADERS]; + IDirect3DSurface9 *BlockSurface[2]; IDirect3DSurface9 *OldRenderTarget; IDirect3DTexture9 *InitialWipeScreen, *FinalWipeScreen;