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;