From 81e7ce9ad29e1eea6b85c0b574509d72972c6e0e Mon Sep 17 00:00:00 2001 From: rice1964 Date: Sun, 20 Sep 2009 03:29:43 +0000 Subject: [PATCH] D3D: get rid of flickering in various games by changing way and time to flip backbuffer to frontbuffer. Also added some debugging messages. ZTP intro seems to be additionally 10%+ faster now, maybe only for me in windows mode. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4303 8ced0084-cf51-0410-be5f-012b33b47a6e --- .../Plugin_VideoDX9/Src/BPFunctions.cpp | 7 +- .../Plugins/Plugin_VideoDX9/Src/D3DBase.cpp | 3 + Source/Plugins/Plugin_VideoDX9/Src/D3DBase.h | 1 + .../Plugin_VideoDX9/Src/Debugger/Debugger.h | 43 ++++++------ Source/Plugins/Plugin_VideoDX9/Src/Render.cpp | 69 ++++++++++++------- .../Plugin_VideoDX9/Src/TextureCache.cpp | 4 ++ .../Plugin_VideoDX9/Src/VertexManager.cpp | 21 ++++-- Source/Plugins/Plugin_VideoDX9/Src/main.cpp | 56 ++++++++++++--- 8 files changed, 139 insertions(+), 65 deletions(-) diff --git a/Source/Plugins/Plugin_VideoDX9/Src/BPFunctions.cpp b/Source/Plugins/Plugin_VideoDX9/Src/BPFunctions.cpp index b053c93648..06e73b7dee 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/BPFunctions.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/BPFunctions.cpp @@ -23,6 +23,7 @@ #include "VertexManager.h" #include "VertexShaderManager.h" #include "Utils.h" +#include "debugger/debugger.h" bool textureChanged[8]; @@ -209,6 +210,9 @@ void CopyEFB(const BPCmd &bp, const EFBRectangle &rc, const u32 &address, const //TextureConverter::EncodeToRam(address, fromZBuffer, isIntensityFmt, copyfmt, scaleByHalf, rc); //else // To D3D Texture TextureCache::CopyRenderTargetToTexture(address, fromZBuffer, isIntensityFmt, copyfmt, scaleByHalf, rc); + DEBUGGER_PAUSE_LOG_AT(NEXT_EFB_CMD,false, + {printf("EFB to texture: addr = %08X\n",address);}); + } } @@ -229,8 +233,7 @@ void ClearScreen(const BPCmd &bp, const EFBRectangle &rc) if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate) { - if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate) - col = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB; + col = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB; clearflags |= D3DCLEAR_TARGET; // set to break animal crossing :p ?? } diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp b/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp index b37a4e4c29..874877a7ff 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp @@ -402,7 +402,10 @@ void EndFrame() return; } bFrameInProgress = false; +} +void Present() +{ if (dev) { dev->EndScene(); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.h b/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.h index 557eef1d9e..40ab5c6237 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.h @@ -54,6 +54,7 @@ extern bool bFrameInProgress; void Reset(); bool BeginFrame(); void EndFrame(); +void Present(); void SwitchFullscreen(bool fullscreen); bool IsFullscreen(); bool CanUseINTZ(); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Debugger/Debugger.h b/Source/Plugins/Plugin_VideoDX9/Src/Debugger/Debugger.h index 5ddc778110..7c6b6e4f2a 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Debugger/Debugger.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/Debugger/Debugger.h @@ -118,32 +118,27 @@ private: }; enum PauseEvent { - NEXT_FRAME, - NEXT_FLUSH, + NOT_PAUSE = 0, + NEXT_FRAME = 1<<0, + NEXT_FLUSH = 1<<1, - NEXT_PIXEL_SHADER_CHANGE, - NEXT_VERTEX_SHADER_CHANGE, - NEXT_TEXTURE_CHANGE, - NEXT_NEW_TEXTURE, + NEXT_PIXEL_SHADER_CHANGE = 1<<2, + NEXT_VERTEX_SHADER_CHANGE = 1<<3, + NEXT_TEXTURE_CHANGE = 1<<4, + NEXT_NEW_TEXTURE = 1<<5, - NEXT_XFB_CMD, - NEXT_EFB_CMD, + NEXT_XFB_CMD = 1<<6, + NEXT_EFB_CMD = 1<<7, - NEXT_MATRIX_CMD, - NEXT_VERTEX_CMD, - NEXT_TEXTURE_CMD, - NEXT_LIGHT_CMD, - NEXT_FOG_CMD, + NEXT_MATRIX_CMD = 1<<8, + NEXT_VERTEX_CMD = 1<<9, + NEXT_TEXTURE_CMD = 1<<10, + NEXT_LIGHT_CMD = 1<<11, + NEXT_FOG_CMD = 1<<12, - NEXT_SET_TLUT, + NEXT_SET_TLUT = 1<<13, - NEXT_FIFO, - NEXT_DLIST, - NEXT_UCODE, - - NEXT_ERROR, - - NOT_PAUSE, + NEXT_ERROR = 1<<14, }; extern volatile bool DX9DebuggerPauseFlag; @@ -160,13 +155,15 @@ void DX9DebuggerToPause(bool update); #ifdef ENABLE_DX_DEBUGGER -#define DEBUGGER_PAUSE_AT(event,update) {if ((DX9DebuggerToPauseAtNext == event && --DX9DebuggerEventToPauseCount<=0) || DX9DebuggerPauseFlag) DX9DebuggerToPause(update);} -#define DEBUGGER_PAUSE_LOG_AT(event,update,dumpfunc) {if ((DX9DebuggerToPauseAtNext == event && --DX9DebuggerEventToPauseCount<=0) || DX9DebuggerPauseFlag) {{dumpfunc};DX9DebuggerToPause(update);}} +#define DEBUGGER_PAUSE_AT(event,update) {if (((DX9DebuggerToPauseAtNext & event) && --DX9DebuggerEventToPauseCount<=0) || DX9DebuggerPauseFlag) DX9DebuggerToPause(update);} +#define DEBUGGER_PAUSE_LOG_AT(event,update,dumpfunc) {if (((DX9DebuggerToPauseAtNext & event) && --DX9DebuggerEventToPauseCount<=0) || DX9DebuggerPauseFlag) {{dumpfunc};DX9DebuggerToPause(update);}} +#define DEBUGGER_LOG_AT(event,dumpfunc) {if (( DX9DebuggerToPauseAtNext & event ) ) {{dumpfunc};}} #else // Not to use debugger in release build #define DEBUGGER_PAUSE_AT(event,update) #define DEBUGGER_PAUSE_LOG_AT(event,update,dumpfunc) +#define DEBUGGER_LOG_AT(event,dumpfunc) #endif ENABLE_DX_DEBUGGER diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp index 8f6f486eb3..5d56a7cd3c 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp @@ -157,6 +157,7 @@ void Renderer::Shutdown() { TeardownDeviceObjects(); D3D::EndFrame(); + D3D::Present(); D3D::Close(); if (s_AVIDumping) @@ -319,6 +320,14 @@ void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRect D3D::dev->StretchRect(FBManager::GetEFBColorRTSurface(), src_rect.AsRECT(), D3D::GetBackBufferSurface(), dst_rect.AsRECT(), D3DTEXF_LINEAR); + DEBUGGER_LOG_AT((NEXT_XFB_CMD|NEXT_EFB_CMD|NEXT_FRAME), + {printf("StretchRect, EFB->XFB\n");}); + DEBUGGER_PAUSE_LOG_AT( + (NEXT_XFB_CMD),false, + {printf("RenderToXFB: addr = %08X, %d x %d, sourceRc = (%d,%d,%d,%d)\n", + xfbAddr, fbWidth, fbHeight, + sourceRc.left, sourceRc.top, sourceRc.right, sourceRc.bottom);} + ); // Finish up the current frame, print some stats if (g_ActiveConfig.bOverlayStats) @@ -335,34 +344,11 @@ void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRect OSD::DrawMessages(); D3D::EndFrame(); - // D3D frame is now over - // Clean out old stuff from caches. - frameCount++; - PixelShaderCache::Cleanup(); - VertexShaderCache::Cleanup(); - TextureCache::Cleanup(); - - // Make any new configuration settings active. - UpdateActiveConfig(); - - // TODO: Resize backbuffer if window size has changed. This code crashes, debug it. - g_VideoInitialize.pCopiedToXFB(false); - - CheckForResize(); - - DEBUGGER_PAUSE_LOG_AT(NEXT_XFB_CMD,false,{printf("RenderToXFB");}); - DEBUGGER_PAUSE_AT(NEXT_FRAME,false); - - - - // Begin new frame - // Set default viewport and scissor, for the clear to work correctly - stats.ResetFrame(); // u32 clearColor = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB; D3D::BeginFrame(); - // Clear backbuffer. We probably don't need to do this every frame. - D3D::dev->Clear(0, NULL, D3DCLEAR_TARGET, 0x0, 1.0f, 0); + // Clear the render target. We probably don't need to do this every frame. + //D3D::dev->Clear(0, NULL, D3DCLEAR_TARGET, 0x0, 1.0f, 0); D3D::dev->SetRenderTarget(0, FBManager::GetEFBColorRTSurface()); D3D::dev->SetDepthStencilSurface(FBManager::GetEFBDepthRTSurface()); @@ -376,6 +362,9 @@ void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRect D3D::SetRenderState(D3DRS_SCISSORTESTENABLE, false); UpdateViewport(); + + //Swap(0,FIELD_PROGRESSIVE,0,0); // we used to swap the buffer here, now we will wait + // until the XFB pointer is updated by VI } bool Renderer::SetScissorRect() @@ -529,3 +518,33 @@ void UpdateViewport() D3D::dev->SetViewport(&vp); } + +void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight) +{ + // this function is called after the XFB field is changed, not after + // EFB is copied to XFB. In this way, flickering is reduced in games + // and seems to also give more FPS in ZTP + + // D3D frame is now over + // Clean out old stuff from caches. + frameCount++; + PixelShaderCache::Cleanup(); + VertexShaderCache::Cleanup(); + TextureCache::Cleanup(); + + // Make any new configuration settings active. + UpdateActiveConfig(); + + //TODO: Resize backbuffer if window size has changed. This code crashes, debug it. + g_VideoInitialize.pCopiedToXFB(false); + + CheckForResize(); + + + // Begin new frame + // Set default viewport and scissor, for the clear to work correctly + stats.ResetFrame(); + + // Flip/present backbuffer to frontbuffer here + D3D::Present(); +} diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp index 8141c37651..db4f5d0247 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp @@ -317,4 +317,8 @@ have_texture: srcSurface = FBManager::GetEFBColorRTSurface(); D3D::dev->StretchRect(srcSurface, &source_rc, destSurface, &dest_rc, D3DTEXF_LINEAR); destSurface->Release(); + + DEBUGGER_LOG_AT((NEXT_XFB_CMD|NEXT_EFB_CMD|NEXT_FRAME|NEXT_NEW_TEXTURE|NEXT_FLUSH), + {printf("StretchRect, EFB (%d,%d) -> Texture at 0x%08X (%d,%d)\n",efb_w,efb_h,address,tex_w,tex_h);}); + DEBUGGER_PAUSE_AT((NEXT_EFB_CMD|NEXT_NEW_TEXTURE),false); } diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp index b19ddf5c06..a6ceeaeded 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp @@ -273,7 +273,10 @@ void Flush() PixelShaderManager::SetTexDims(i, tentry->w, tentry->h, 0, 0); } else + { + DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to load texture\n");}); ERROR_LOG(VIDEO, "error loading texture"); + } } } PixelShaderManager::SetTexturesUsed(0); @@ -285,10 +288,17 @@ void Flush() VertexShaderManager::SetConstants(); PixelShaderManager::SetConstants(); - if (!VertexShaderCache::SetShader(g_nativeVertexFmt->m_components)) - goto shader_fail; if (!PixelShaderCache::SetShader(false)) + { + DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");}); goto shader_fail; + } + if (!VertexShaderCache::SetShader(g_nativeVertexFmt->m_components)) + { + DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set vertex shader\n");}); + goto shader_fail; + + } int stride = g_nativeVertexFmt->GetVertexStride(); g_nativeVertexFmt->SetupVertexPointers(); @@ -299,7 +309,11 @@ void Flush() { DWORD write = 0; if (!PixelShaderCache::SetShader(true)) + { + DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");}); goto shader_fail; + } + // update alpha only D3D::SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA); D3D::SetRenderState(D3DRS_ALPHABLENDENABLE, false); @@ -315,13 +329,12 @@ void Flush() D3D::SetRenderState(D3DRS_COLORWRITEENABLE, write); } + DEBUGGER_PAUSE_AT(NEXT_FLUSH,true); } shader_fail: collection = C_NOTHING; VertexManager::s_pCurBufferPointer = fakeVBuffer; - DEBUGGER_PAUSE_AT(NEXT_FLUSH,true); } - //DX9DEBUGGER_PAUSE_IF(NEXT_FLUSH); } } // namespace diff --git a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp index e344a7bec8..30b9cccd21 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp @@ -24,6 +24,7 @@ #include "Thread.h" #include "LogManager.h" #include "GlobalControl.h" +#include "debugger/debugger.h" #if defined(HAVE_WX) && HAVE_WX #include "Debugger/Debugger.h" @@ -52,6 +53,8 @@ GFXDebuggerDX9 *m_DebuggerFrame = NULL; #include "EmuWindow.h" #include "VideoState.h" #include "XFBConvert.h" +#include "render.h" + // Having to include this is TERRIBLY ugly. FIXME x100 #include "../../../Core/Core/Src/ConfigManager.h" // FIXME @@ -64,6 +67,14 @@ PLUGIN_GLOBALS* globals = NULL; bool s_initialized; static u32 s_efbAccessRequested = FALSE; +static bool s_swapRequested = false; +static volatile struct +{ + u32 xfbAddr; + FieldType field; + u32 fbWidth; + u32 fbHeight; +} s_beginFieldArgs; static volatile EFBAccessType s_AccessEFBType; @@ -308,31 +319,54 @@ void Video_SendFifoData(u8* _uData, u32 len) Fifo_SendFifoData(_uData, len); } +// Run from the graphics thread void VideoFifo_CheckSwapRequest() { - // CPU swap unimplemented + // CPU swap, not finished, seems to be working fine for dual-core for now + + if (s_swapRequested) + { + // Flip the backbuffer to front buffer now + s_swapRequested = false; + if (s_beginFieldArgs.field == FIELD_PROGRESSIVE || s_beginFieldArgs.field == FIELD_LOWER) + { + Renderer::Swap(0,FIELD_PROGRESSIVE,0,0); // The swap function is not finished + // so it is ok to pass dummy parameters for now + } + } } +// Run from the graphics thread void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight) { // CPU swap unimplemented } +// Run from the CPU thread (from VideoInterface.cpp) void Video_BeginField(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight) { - /* - ConvertXFB(tempBuffer, _pXFB, _dwWidth, _dwHeight); + s_beginFieldArgs.xfbAddr = xfbAddr; + s_beginFieldArgs.field = field; + s_beginFieldArgs.fbWidth = fbWidth; + s_beginFieldArgs.fbHeight = fbHeight; + s_swapRequested = true; - // blubb - static LPDIRECT3DTEXTURE9 pTexture = D3D::CreateTexture2D((BYTE*)tempBuffer, _dwWidth, _dwHeight, _dwWidth, D3DFMT_A8R8G8B8); + if (s_initialized) + { - D3D::ReplaceTexture2D(pTexture, (BYTE*)tempBuffer, _dwWidth, _dwHeight, _dwWidth, D3DFMT_A8R8G8B8); - D3D::dev->SetTexture(0, pTexture); + // Make sure previous swap request has made it to the screen + if (g_VideoInitialize.bUseDualCore) + { + // It seems to be working fine in this way for now without using AtomicLoadAcquire + // ector, please check here + //while (Common::AtomicLoadAcquire(s_swapRequested)) + // Common::YieldCPU(); + } + else + VideoFifo_CheckSwapRequest(); - D3D::quad2d(0,0,(float)Postprocess::GetWidth(),(float)Postprocess::GetHeight(), 0xFFFFFFFF); - - D3D::EndFrame(); - D3D::BeginFrame();*/ + } + DEBUGGER_LOG_AT(NEXT_XFB_CMD,{printf("Begin Field: %08x, %d x %d\n",xfbAddr,fbWidth,fbHeight);}); } void Video_EndField()