Frameskipping! Complete with GUI! Even my most naive approach resulted in great speeds, even with graphic-intensive games such as Pikmin.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3949 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
XTra.KrazzY 2009-08-08 01:39:56 +00:00
parent 9cbfadb885
commit 51ddedf512
21 changed files with 126 additions and 19 deletions

View File

@ -50,6 +50,8 @@ PluginVideo::PluginVideo(const char *_Filename) : CPlugin(_Filename), validVideo
(LoadSymbol("Video_AddMessage")); (LoadSymbol("Video_AddMessage"));
Video_AccessEFB = reinterpret_cast<TVideo_AccessEFB> Video_AccessEFB = reinterpret_cast<TVideo_AccessEFB>
(LoadSymbol("Video_AccessEFB")); (LoadSymbol("Video_AccessEFB"));
Video_SetRendering = reinterpret_cast<TVideo_SetRendering>
(LoadSymbol("Video_SetRendering"));
if ((Video_Prepare != 0) && if ((Video_Prepare != 0) &&
(Video_SendFifoData != 0) && (Video_SendFifoData != 0) &&
@ -59,6 +61,7 @@ PluginVideo::PluginVideo(const char *_Filename) : CPlugin(_Filename), validVideo
(Video_ExitLoop != 0) && (Video_ExitLoop != 0) &&
(Video_Screenshot != 0) && (Video_Screenshot != 0) &&
(Video_AddMessage != 0) && (Video_AddMessage != 0) &&
(Video_SetRendering != 0) &&
(Video_AccessEFB != 0)) (Video_AccessEFB != 0))
validVideo = true; validVideo = true;
} }

View File

@ -30,6 +30,7 @@ typedef void (__cdecl* TVideo_EndField)();
typedef bool (__cdecl* TVideo_Screenshot)(const char* filename); typedef bool (__cdecl* TVideo_Screenshot)(const char* filename);
typedef void (__cdecl* TVideo_EnterLoop)(); typedef void (__cdecl* TVideo_EnterLoop)();
typedef void (__cdecl* TVideo_ExitLoop)(); typedef void (__cdecl* TVideo_ExitLoop)();
typedef void (__cdecl* TVideo_SetRendering)(bool bEnabled);
typedef void (__cdecl* TVideo_AddMessage)(const char* pstr, unsigned int milliseconds); typedef void (__cdecl* TVideo_AddMessage)(const char* pstr, unsigned int milliseconds);
typedef u32 (__cdecl* TVideo_AccessEFB)(EFBAccessType, u32, u32); typedef u32 (__cdecl* TVideo_AccessEFB)(EFBAccessType, u32, u32);
@ -51,6 +52,8 @@ public:
TVideo_AddMessage Video_AddMessage; TVideo_AddMessage Video_AddMessage;
TVideo_Screenshot Video_Screenshot; TVideo_Screenshot Video_Screenshot;
TVideo_SetRendering Video_SetRendering;
private: private:
bool validVideo; bool validVideo;
}; };

View File

@ -2244,14 +2244,6 @@
RelativePath=".\Src\CoreTiming.h" RelativePath=".\Src\CoreTiming.h"
> >
</File> </File>
<File
RelativePath=".\Src\Frame.cpp"
>
</File>
<File
RelativePath=".\Src\Frame.h"
>
</File>
<File <File
RelativePath=".\Src\Host.h" RelativePath=".\Src\Host.h"
> >
@ -2264,6 +2256,14 @@
RelativePath=".\Src\MemTools.h" RelativePath=".\Src\MemTools.h"
> >
</File> </File>
<File
RelativePath=".\Src\OnFrame.cpp"
>
</File>
<File
RelativePath=".\Src\OnFrame.h"
>
</File>
<File <File
RelativePath=".\Src\PatchEngine.cpp" RelativePath=".\Src\PatchEngine.cpp"
> >

View File

@ -56,7 +56,7 @@
#include "LogManager.h" #include "LogManager.h"
#include "State.h" #include "State.h"
#include "Frame.h" #include "OnFrame.h"
#ifndef _WIN32 #ifndef _WIN32
#define WINAPI #define WINAPI
@ -604,9 +604,9 @@ void Callback_VideoCopiedToXFB(bool video_update)
static u32 videoupd = 0; static u32 videoupd = 0;
if (video_update) if (video_update)
videoupd++; videoupd += Frame::FrameSkippingFactor() + 1;
else else
frames++; frames += Frame::FrameSkippingFactor() + 1;
// Custom frame limiter // Custom frame limiter
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

View File

@ -25,7 +25,7 @@
#include "EXI_Device.h" #include "EXI_Device.h"
#include "EXI_DeviceMic.h" #include "EXI_DeviceMic.h"
#include "../Frame.h" #include "../OnFrame.h"
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// --- standard gamecube controller --- // --- standard gamecube controller ---

View File

@ -15,6 +15,8 @@
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "OnFrame.h"
#include "Core.h" #include "Core.h"
#include "PluginManager.h" #include "PluginManager.h"
@ -25,12 +27,27 @@ bool g_bAutoFire = false;
u32 g_autoFirstKey = 0, g_autoSecondKey = 0; u32 g_autoFirstKey = 0, g_autoSecondKey = 0;
bool g_bFirstKey = true; bool g_bFirstKey = true;
int g_framesToSkip = 1, g_frameSkipCounter = 0;
void FrameUpdate() { void FrameUpdate() {
if(g_bFrameStep) if(g_bFrameStep)
Core::SetState(Core::CORE_PAUSE); Core::SetState(Core::CORE_PAUSE);
if(g_bAutoFire) if(g_bAutoFire)
g_bFirstKey = !g_bFirstKey; g_bFirstKey = !g_bFirstKey;
if(g_framesToSkip)
FrameSkipping();
}
void SetFrameSkipping(unsigned int framesToSkip) {
g_framesToSkip = (int)framesToSkip;
g_frameSkipCounter = 0;
}
int FrameSkippingFactor() {
return g_framesToSkip;
} }
void SetAutoHold(bool bEnabled, u32 keyToHold) { void SetAutoHold(bool bEnabled, u32 keyToHold) {
@ -60,7 +77,6 @@ void SetFrameStepping(bool bEnabled) {
g_bFrameStep = bEnabled; g_bFrameStep = bEnabled;
} }
void ModifyController(SPADStatus *PadStatus) { void ModifyController(SPADStatus *PadStatus) {
u32 keyToPress = (g_bFirstKey) ? g_autoFirstKey : g_autoSecondKey; u32 keyToPress = (g_bFirstKey) ? g_autoFirstKey : g_autoSecondKey;
@ -90,4 +106,12 @@ void ModifyController(SPADStatus *PadStatus) {
} }
void FrameSkipping() {
g_frameSkipCounter++;
if(g_frameSkipCounter > g_framesToSkip)
g_frameSkipCounter = 0;
CPluginManager::GetInstance().GetVideo()->Video_SetRendering(!g_frameSkipCounter);
}
}; };

View File

@ -18,6 +18,9 @@
#ifndef __FRAME_H #ifndef __FRAME_H
#define __FRAME_H #define __FRAME_H
#include "Common.h"
#include "pluginspecs_pad.h"
// Per-(video )Frame actions // Per-(video )Frame actions
namespace Frame { namespace Frame {
@ -33,6 +36,10 @@ void SetFrameStepping(bool bEnabled);
void ModifyController(SPADStatus *PadStatus); void ModifyController(SPADStatus *PadStatus);
void SetFrameSkipping(unsigned int framesToSkip);
int FrameSkippingFactor();
void FrameSkipping();
}; };
#endif // __FRAME_H #endif // __FRAME_H

View File

@ -11,7 +11,7 @@ files = ["ActionReplay.cpp",
"CoreParameter.cpp", "CoreParameter.cpp",
"CoreRerecording.cpp", "CoreRerecording.cpp",
"CoreTiming.cpp", "CoreTiming.cpp",
"Frame.cpp", "OnFrame.cpp",
"Host.cpp", "Host.cpp",
"MemTools.cpp", "MemTools.cpp",
"PatchEngine.cpp", "PatchEngine.cpp",

View File

@ -278,6 +278,7 @@ EVT_MENU(IDM_SAVESTATEFILE, CFrame::OnSaveStateToFile)
EVT_MENU_RANGE(IDM_LOADSLOT1, IDM_LOADSLOT8, CFrame::OnLoadState) EVT_MENU_RANGE(IDM_LOADSLOT1, IDM_LOADSLOT8, CFrame::OnLoadState)
EVT_MENU_RANGE(IDM_SAVESLOT1, IDM_SAVESLOT8, CFrame::OnSaveState) EVT_MENU_RANGE(IDM_SAVESLOT1, IDM_SAVESLOT8, CFrame::OnSaveState)
EVT_MENU_RANGE(IDM_FRAMESKIP0, IDM_FRAMESKIP9, CFrame::OnFrameSkip)
EVT_MENU_RANGE(IDM_DRIVE1, IDM_DRIVE24, CFrame::OnBootDrive) EVT_MENU_RANGE(IDM_DRIVE1, IDM_DRIVE24, CFrame::OnBootDrive)
EVT_SIZE(CFrame::OnResize) EVT_SIZE(CFrame::OnResize)

View File

@ -170,6 +170,8 @@ class CFrame : public wxFrame
void OnUndoLoadState(wxCommandEvent& event); void OnUndoLoadState(wxCommandEvent& event);
void OnUndoSaveState(wxCommandEvent& event); void OnUndoSaveState(wxCommandEvent& event);
void OnFrameSkip(wxCommandEvent& event);
void OnConfigMain(wxCommandEvent& event); // Options void OnConfigMain(wxCommandEvent& event); // Options
void OnPluginGFX(wxCommandEvent& event); void OnPluginGFX(wxCommandEvent& event);
void OnPluginDSP(wxCommandEvent& event); void OnPluginDSP(wxCommandEvent& event);
@ -210,6 +212,7 @@ class CFrame : public wxFrame
// Emulation // Emulation
wxMenuItem* m_pSubMenuLoad; wxMenuItem* m_pSubMenuLoad;
wxMenuItem* m_pSubMenuSave; wxMenuItem* m_pSubMenuSave;
wxMenuItem* m_pSubMenuFrameSkipping;
void BootGame(); void BootGame();

View File

@ -59,6 +59,7 @@ Core::GetWindowHandle().
#include "ConfigManager.h" // Core #include "ConfigManager.h" // Core
#include "Core.h" #include "Core.h"
#include "OnFrame.h"
#include "HW/DVDInterface.h" #include "HW/DVDInterface.h"
#include "State.h" #include "State.h"
#include "VolumeHandler.h" #include "VolumeHandler.h"
@ -130,6 +131,12 @@ void CFrame::CreateMenu()
emulationMenu->Append(IDM_PLAY, _T("&Play\tF10")); emulationMenu->Append(IDM_PLAY, _T("&Play\tF10"));
emulationMenu->Append(IDM_CHANGEDISC, _T("Change &Disc")); emulationMenu->Append(IDM_CHANGEDISC, _T("Change &Disc"));
emulationMenu->Append(IDM_STOP, _T("&Stop")); emulationMenu->Append(IDM_STOP, _T("&Stop"));
wxMenu *skippingMenu = new wxMenu;
m_pSubMenuFrameSkipping = emulationMenu->AppendSubMenu(skippingMenu, _T("&Frame Skipping"));
for(int i = 0; i < 10; i++)
skippingMenu->Append(IDM_FRAMESKIP0 + i, wxString::Format(_T("%i"), i), wxEmptyString, wxITEM_RADIO);
emulationMenu->AppendSeparator(); emulationMenu->AppendSeparator();
emulationMenu->Append(IDM_SCREENSHOT, _T("Take S&creenshot\tF9")); emulationMenu->Append(IDM_SCREENSHOT, _T("Take S&creenshot\tF9"));
emulationMenu->AppendSeparator(); emulationMenu->AppendSeparator();
@ -713,6 +720,13 @@ void CFrame::OnSaveState(wxCommandEvent& event)
State_Save(slot); State_Save(slot);
} }
void CFrame::OnFrameSkip(wxCommandEvent& event)
{
int amount = event.GetId() - IDM_FRAMESKIP0;
Frame::SetFrameSkipping((unsigned int)amount);
}
void CFrame::OnResize(wxSizeEvent& event) void CFrame::OnResize(wxSizeEvent& event)
{ {
FitInside(); FitInside();
@ -817,6 +831,7 @@ void CFrame::UpdateGUI()
GetMenuBar()->FindItem(IDM_SCREENSHOT)->Enable(running || paused); GetMenuBar()->FindItem(IDM_SCREENSHOT)->Enable(running || paused);
m_pSubMenuLoad->Enable(initialized); m_pSubMenuLoad->Enable(initialized);
m_pSubMenuSave->Enable(initialized); m_pSubMenuSave->Enable(initialized);
m_pSubMenuFrameSkipping->Enable(initialized);
// Misc // Misc
GetMenuBar()->FindItem(IDM_CHANGEDISC)->Enable(initialized); GetMenuBar()->FindItem(IDM_CHANGEDISC)->Enable(initialized);

View File

@ -51,6 +51,16 @@ enum
IDM_LOADSLOT6, IDM_LOADSLOT6,
IDM_LOADSLOT7, IDM_LOADSLOT7,
IDM_LOADSLOT8, IDM_LOADSLOT8,
IDM_FRAMESKIP0,
IDM_FRAMESKIP1,
IDM_FRAMESKIP2,
IDM_FRAMESKIP3,
IDM_FRAMESKIP4,
IDM_FRAMESKIP5,
IDM_FRAMESKIP6,
IDM_FRAMESKIP7,
IDM_FRAMESKIP8,
IDM_FRAMESKIP9,
IDM_PLAY, IDM_PLAY,
IDM_STOP, IDM_STOP,
IDM_SCREENSHOT, IDM_SCREENSHOT,

View File

@ -24,6 +24,7 @@
#include "Fifo.h" #include "Fifo.h"
volatile bool g_bSkipCurrentFrame = false;
extern u8* g_pVideoData; extern u8* g_pVideoData;
@ -77,6 +78,10 @@ u8* FAKE_GetFifoEndPtr()
return &videoBuffer[size]; return &videoBuffer[size];
} }
void Fifo_SetRendering(bool bEnabled) {
g_bSkipCurrentFrame = !bEnabled;
}
// Executed from another thread, no the graphics thread! // Executed from another thread, no the graphics thread!
// Basically, all it does is set a flag so that the loop will eventually exit, then // Basically, all it does is set a flag so that the loop will eventually exit, then
// waits for the event to be set, which happens when the loop does exit. // waits for the event to be set, which happens when the loop does exit.

View File

@ -25,6 +25,8 @@
#define FIFO_SIZE (1024*1024) #define FIFO_SIZE (1024*1024)
extern volatile bool g_bSkipCurrentFrame;
void Fifo_Init(); void Fifo_Init();
void Fifo_Shutdown(); void Fifo_Shutdown();
@ -37,6 +39,8 @@ void Fifo_ExitLoopNonBlocking();
void Fifo_DoState(PointerWrap &f); void Fifo_DoState(PointerWrap &f);
void Fifo_SetRendering(bool bEnabled);
// Implemented by the Video Plugin // Implemented by the Video Plugin
void VideoFifo_CheckSwapRequest(); void VideoFifo_CheckSwapRequest();
void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight); void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight);

View File

@ -197,6 +197,7 @@ bool FifoCommandRunnable()
static void Decode() static void Decode()
{ {
int Cmd = DataReadU8(); int Cmd = DataReadU8();
switch(Cmd) switch(Cmd)
{ {
case GX_NOP: case GX_NOP:
@ -268,6 +269,7 @@ static void Decode()
{ {
// load vertices (use computed vertex size from FifoCommandRunnable above) // load vertices (use computed vertex size from FifoCommandRunnable above)
u16 numVertices = DataReadU16(); u16 numVertices = DataReadU16();
VertexLoaderManager::RunVertices( VertexLoaderManager::RunVertices(
Cmd & GX_VAT_MASK, // Vertex loader index (0 - 7) Cmd & GX_VAT_MASK, // Vertex loader index (0 - 7)
(Cmd & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT, (Cmd & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT,

View File

@ -115,6 +115,7 @@ void RunVertices(int vtx_attr_group, int primitive, int count)
{ {
if (!count) if (!count)
return; return;
RefreshLoader(vtx_attr_group); RefreshLoader(vtx_attr_group);
g_VertexLoaders[vtx_attr_group]->RunVertices(vtx_attr_group, primitive, count); g_VertexLoaders[vtx_attr_group]->RunVertices(vtx_attr_group, primitive, count);
} }

View File

@ -164,6 +164,14 @@ EXPORT void CALL Video_EnterLoop(void);
// //
EXPORT void CALL Video_ExitLoop(void); EXPORT void CALL Video_ExitLoop(void);
// __________________________________________________________________________________________________
// Function: Video_SetRendering
// Purpose: Sets video rendering on and off. Currently used for frame skipping
// input: Enabled toggle
// output: none
//
EXPORT void CALL Video_SetRendering(bool bEnabled);
// __________________________________________________________________________________________________ // __________________________________________________________________________________________________
// Function: Video_AddMessage // Function: Video_AddMessage
// Purpose: Adds a message to the display queue, to be shown forthe specified time // Purpose: Adds a message to the display queue, to be shown forthe specified time

View File

@ -222,6 +222,9 @@ void Video_ExitLoop()
Fifo_ExitLoop(); Fifo_ExitLoop();
} }
void Video_SetRendering(bool bEnabled) {
Fifo_SetRendering(bEnabled);
}
void Video_Prepare(void) void Video_Prepare(void)
{ {

View File

@ -116,6 +116,8 @@ static int s_targetheight;
static FramebufferManager s_framebufferManager; static FramebufferManager s_framebufferManager;
static GLuint s_tempScreenshotFramebuffer = 0; static GLuint s_tempScreenshotFramebuffer = 0;
static bool s_skipSwap = false;
#ifndef _WIN32 #ifndef _WIN32
int OSDChoice = 0 , OSDTime = 0, OSDInternalW = 0, OSDInternalH = 0; int OSDChoice = 0 , OSDTime = 0, OSDInternalW = 0, OSDInternalH = 0;
#endif #endif
@ -791,6 +793,8 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaE
void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc) void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
{ {
s_skipSwap = g_bSkipCurrentFrame;
g_VideoInitialize.pCopiedToXFB(false); g_VideoInitialize.pCopiedToXFB(false);
#ifdef XXX_ENABLE_CPU_CONTROLLED_SWAPPING #ifdef XXX_ENABLE_CPU_CONTROLLED_SWAPPING
@ -814,6 +818,9 @@ void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRect
// This function has the final picture. We adjust the aspect ratio here. // This function has the final picture. We adjust the aspect ratio here.
void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight) void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
{ {
if(s_skipSwap)
return;
const XFBSource* xfbSource = s_framebufferManager.GetXFBSource(xfbAddr, fbWidth, fbHeight); const XFBSource* xfbSource = s_framebufferManager.GetXFBSource(xfbAddr, fbWidth, fbHeight);
if (!xfbSource) if (!xfbSource)
{ {

View File

@ -20,6 +20,8 @@
#include <fstream> #include <fstream>
#include <vector> #include <vector>
#include "Fifo.h"
#include "Config.h" #include "Config.h"
#include "Statistics.h" #include "Statistics.h"
#include "MemoryUtil.h" #include "MemoryUtil.h"
@ -185,6 +187,11 @@ void Flush()
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
if(g_bSkipCurrentFrame) {
ResetBuffer();
return;
}
glBindBuffer(GL_ARRAY_BUFFER, s_vboBuffers[s_nCurVBOIndex]); glBindBuffer(GL_ARRAY_BUFFER, s_vboBuffers[s_nCurVBOIndex]);
glBufferData(GL_ARRAY_BUFFER, s_pCurBufferPointer - s_pBaseBufferPointer, s_pBaseBufferPointer, GL_STREAM_DRAW); glBufferData(GL_ARRAY_BUFFER, s_pCurBufferPointer - s_pBaseBufferPointer, s_pBaseBufferPointer, GL_STREAM_DRAW);
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();

View File

@ -448,6 +448,10 @@ void Video_AddMessage(const char* pstr, u32 milliseconds)
OSD::AddMessage(pstr, milliseconds); OSD::AddMessage(pstr, milliseconds);
} }
void Video_SetRendering(bool bEnabled) {
Fifo_SetRendering(bEnabled);
}
static volatile struct static volatile struct
{ {
u32 xfbAddr; u32 xfbAddr;