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:
parent
9cbfadb885
commit
51ddedf512
|
@ -50,6 +50,8 @@ PluginVideo::PluginVideo(const char *_Filename) : CPlugin(_Filename), validVideo
|
|||
(LoadSymbol("Video_AddMessage"));
|
||||
Video_AccessEFB = reinterpret_cast<TVideo_AccessEFB>
|
||||
(LoadSymbol("Video_AccessEFB"));
|
||||
Video_SetRendering = reinterpret_cast<TVideo_SetRendering>
|
||||
(LoadSymbol("Video_SetRendering"));
|
||||
|
||||
if ((Video_Prepare != 0) &&
|
||||
(Video_SendFifoData != 0) &&
|
||||
|
@ -59,6 +61,7 @@ PluginVideo::PluginVideo(const char *_Filename) : CPlugin(_Filename), validVideo
|
|||
(Video_ExitLoop != 0) &&
|
||||
(Video_Screenshot != 0) &&
|
||||
(Video_AddMessage != 0) &&
|
||||
(Video_SetRendering != 0) &&
|
||||
(Video_AccessEFB != 0))
|
||||
validVideo = true;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ typedef void (__cdecl* TVideo_EndField)();
|
|||
typedef bool (__cdecl* TVideo_Screenshot)(const char* filename);
|
||||
typedef void (__cdecl* TVideo_EnterLoop)();
|
||||
typedef void (__cdecl* TVideo_ExitLoop)();
|
||||
typedef void (__cdecl* TVideo_SetRendering)(bool bEnabled);
|
||||
typedef void (__cdecl* TVideo_AddMessage)(const char* pstr, unsigned int milliseconds);
|
||||
typedef u32 (__cdecl* TVideo_AccessEFB)(EFBAccessType, u32, u32);
|
||||
|
||||
|
@ -51,6 +52,8 @@ public:
|
|||
TVideo_AddMessage Video_AddMessage;
|
||||
TVideo_Screenshot Video_Screenshot;
|
||||
|
||||
TVideo_SetRendering Video_SetRendering;
|
||||
|
||||
private:
|
||||
bool validVideo;
|
||||
};
|
||||
|
|
|
@ -2244,14 +2244,6 @@
|
|||
RelativePath=".\Src\CoreTiming.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\Frame.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\Frame.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\Host.h"
|
||||
>
|
||||
|
@ -2264,6 +2256,14 @@
|
|||
RelativePath=".\Src\MemTools.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\OnFrame.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\OnFrame.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\PatchEngine.cpp"
|
||||
>
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
#include "LogManager.h"
|
||||
|
||||
#include "State.h"
|
||||
#include "Frame.h"
|
||||
#include "OnFrame.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#define WINAPI
|
||||
|
@ -604,9 +604,9 @@ void Callback_VideoCopiedToXFB(bool video_update)
|
|||
static u32 videoupd = 0;
|
||||
|
||||
if (video_update)
|
||||
videoupd++;
|
||||
videoupd += Frame::FrameSkippingFactor() + 1;
|
||||
else
|
||||
frames++;
|
||||
frames += Frame::FrameSkippingFactor() + 1;
|
||||
|
||||
// Custom frame limiter
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "EXI_Device.h"
|
||||
#include "EXI_DeviceMic.h"
|
||||
|
||||
#include "../Frame.h"
|
||||
#include "../OnFrame.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// --- standard gamecube controller ---
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "OnFrame.h"
|
||||
|
||||
#include "Core.h"
|
||||
#include "PluginManager.h"
|
||||
|
||||
|
@ -25,12 +27,27 @@ bool g_bAutoFire = false;
|
|||
u32 g_autoFirstKey = 0, g_autoSecondKey = 0;
|
||||
bool g_bFirstKey = true;
|
||||
|
||||
int g_framesToSkip = 1, g_frameSkipCounter = 0;
|
||||
|
||||
void FrameUpdate() {
|
||||
if(g_bFrameStep)
|
||||
Core::SetState(Core::CORE_PAUSE);
|
||||
|
||||
if(g_bAutoFire)
|
||||
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) {
|
||||
|
@ -60,7 +77,6 @@ void SetFrameStepping(bool bEnabled) {
|
|||
g_bFrameStep = bEnabled;
|
||||
}
|
||||
|
||||
|
||||
void ModifyController(SPADStatus *PadStatus) {
|
||||
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);
|
||||
}
|
||||
|
||||
};
|
|
@ -18,6 +18,9 @@
|
|||
#ifndef __FRAME_H
|
||||
#define __FRAME_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "pluginspecs_pad.h"
|
||||
|
||||
// Per-(video )Frame actions
|
||||
|
||||
namespace Frame {
|
||||
|
@ -33,6 +36,10 @@ void SetFrameStepping(bool bEnabled);
|
|||
|
||||
void ModifyController(SPADStatus *PadStatus);
|
||||
|
||||
void SetFrameSkipping(unsigned int framesToSkip);
|
||||
int FrameSkippingFactor();
|
||||
void FrameSkipping();
|
||||
|
||||
};
|
||||
|
||||
#endif // __FRAME_H
|
|
@ -11,7 +11,7 @@ files = ["ActionReplay.cpp",
|
|||
"CoreParameter.cpp",
|
||||
"CoreRerecording.cpp",
|
||||
"CoreTiming.cpp",
|
||||
"Frame.cpp",
|
||||
"OnFrame.cpp",
|
||||
"Host.cpp",
|
||||
"MemTools.cpp",
|
||||
"PatchEngine.cpp",
|
||||
|
|
|
@ -278,6 +278,7 @@ EVT_MENU(IDM_SAVESTATEFILE, CFrame::OnSaveStateToFile)
|
|||
|
||||
EVT_MENU_RANGE(IDM_LOADSLOT1, IDM_LOADSLOT8, CFrame::OnLoadState)
|
||||
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_SIZE(CFrame::OnResize)
|
||||
|
|
|
@ -170,6 +170,8 @@ class CFrame : public wxFrame
|
|||
void OnUndoLoadState(wxCommandEvent& event);
|
||||
void OnUndoSaveState(wxCommandEvent& event);
|
||||
|
||||
void OnFrameSkip(wxCommandEvent& event);
|
||||
|
||||
void OnConfigMain(wxCommandEvent& event); // Options
|
||||
void OnPluginGFX(wxCommandEvent& event);
|
||||
void OnPluginDSP(wxCommandEvent& event);
|
||||
|
@ -210,6 +212,7 @@ class CFrame : public wxFrame
|
|||
// Emulation
|
||||
wxMenuItem* m_pSubMenuLoad;
|
||||
wxMenuItem* m_pSubMenuSave;
|
||||
wxMenuItem* m_pSubMenuFrameSkipping;
|
||||
|
||||
void BootGame();
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ Core::GetWindowHandle().
|
|||
|
||||
#include "ConfigManager.h" // Core
|
||||
#include "Core.h"
|
||||
#include "OnFrame.h"
|
||||
#include "HW/DVDInterface.h"
|
||||
#include "State.h"
|
||||
#include "VolumeHandler.h"
|
||||
|
@ -130,6 +131,12 @@ void CFrame::CreateMenu()
|
|||
emulationMenu->Append(IDM_PLAY, _T("&Play\tF10"));
|
||||
emulationMenu->Append(IDM_CHANGEDISC, _T("Change &Disc"));
|
||||
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->Append(IDM_SCREENSHOT, _T("Take S&creenshot\tF9"));
|
||||
emulationMenu->AppendSeparator();
|
||||
|
@ -713,6 +720,13 @@ void CFrame::OnSaveState(wxCommandEvent& event)
|
|||
State_Save(slot);
|
||||
}
|
||||
|
||||
void CFrame::OnFrameSkip(wxCommandEvent& event)
|
||||
{
|
||||
int amount = event.GetId() - IDM_FRAMESKIP0;
|
||||
|
||||
Frame::SetFrameSkipping((unsigned int)amount);
|
||||
}
|
||||
|
||||
void CFrame::OnResize(wxSizeEvent& event)
|
||||
{
|
||||
FitInside();
|
||||
|
@ -817,6 +831,7 @@ void CFrame::UpdateGUI()
|
|||
GetMenuBar()->FindItem(IDM_SCREENSHOT)->Enable(running || paused);
|
||||
m_pSubMenuLoad->Enable(initialized);
|
||||
m_pSubMenuSave->Enable(initialized);
|
||||
m_pSubMenuFrameSkipping->Enable(initialized);
|
||||
|
||||
// Misc
|
||||
GetMenuBar()->FindItem(IDM_CHANGEDISC)->Enable(initialized);
|
||||
|
|
|
@ -51,6 +51,16 @@ enum
|
|||
IDM_LOADSLOT6,
|
||||
IDM_LOADSLOT7,
|
||||
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_STOP,
|
||||
IDM_SCREENSHOT,
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "Fifo.h"
|
||||
|
||||
volatile bool g_bSkipCurrentFrame = false;
|
||||
|
||||
extern u8* g_pVideoData;
|
||||
|
||||
|
@ -77,6 +78,10 @@ u8* FAKE_GetFifoEndPtr()
|
|||
return &videoBuffer[size];
|
||||
}
|
||||
|
||||
void Fifo_SetRendering(bool bEnabled) {
|
||||
g_bSkipCurrentFrame = !bEnabled;
|
||||
}
|
||||
|
||||
// Executed from another thread, no the graphics thread!
|
||||
// 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.
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
#define FIFO_SIZE (1024*1024)
|
||||
|
||||
extern volatile bool g_bSkipCurrentFrame;
|
||||
|
||||
void Fifo_Init();
|
||||
void Fifo_Shutdown();
|
||||
|
||||
|
@ -37,6 +39,8 @@ void Fifo_ExitLoopNonBlocking();
|
|||
|
||||
void Fifo_DoState(PointerWrap &f);
|
||||
|
||||
void Fifo_SetRendering(bool bEnabled);
|
||||
|
||||
// Implemented by the Video Plugin
|
||||
void VideoFifo_CheckSwapRequest();
|
||||
void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight);
|
||||
|
|
|
@ -197,6 +197,7 @@ bool FifoCommandRunnable()
|
|||
static void Decode()
|
||||
{
|
||||
int Cmd = DataReadU8();
|
||||
|
||||
switch(Cmd)
|
||||
{
|
||||
case GX_NOP:
|
||||
|
@ -268,6 +269,7 @@ static void Decode()
|
|||
{
|
||||
// load vertices (use computed vertex size from FifoCommandRunnable above)
|
||||
u16 numVertices = DataReadU16();
|
||||
|
||||
VertexLoaderManager::RunVertices(
|
||||
Cmd & GX_VAT_MASK, // Vertex loader index (0 - 7)
|
||||
(Cmd & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT,
|
||||
|
|
|
@ -115,6 +115,7 @@ void RunVertices(int vtx_attr_group, int primitive, int count)
|
|||
{
|
||||
if (!count)
|
||||
return;
|
||||
|
||||
RefreshLoader(vtx_attr_group);
|
||||
g_VertexLoaders[vtx_attr_group]->RunVertices(vtx_attr_group, primitive, count);
|
||||
}
|
||||
|
|
|
@ -164,6 +164,14 @@ EXPORT void CALL Video_EnterLoop(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
|
||||
// Purpose: Adds a message to the display queue, to be shown forthe specified time
|
||||
|
|
|
@ -222,6 +222,9 @@ void Video_ExitLoop()
|
|||
Fifo_ExitLoop();
|
||||
}
|
||||
|
||||
void Video_SetRendering(bool bEnabled) {
|
||||
Fifo_SetRendering(bEnabled);
|
||||
}
|
||||
|
||||
void Video_Prepare(void)
|
||||
{
|
||||
|
|
|
@ -116,6 +116,8 @@ static int s_targetheight;
|
|||
static FramebufferManager s_framebufferManager;
|
||||
static GLuint s_tempScreenshotFramebuffer = 0;
|
||||
|
||||
static bool s_skipSwap = false;
|
||||
|
||||
#ifndef _WIN32
|
||||
int OSDChoice = 0 , OSDTime = 0, OSDInternalW = 0, OSDInternalH = 0;
|
||||
#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)
|
||||
{
|
||||
s_skipSwap = g_bSkipCurrentFrame;
|
||||
|
||||
g_VideoInitialize.pCopiedToXFB(false);
|
||||
|
||||
#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.
|
||||
void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
|
||||
{
|
||||
if(s_skipSwap)
|
||||
return;
|
||||
|
||||
const XFBSource* xfbSource = s_framebufferManager.GetXFBSource(xfbAddr, fbWidth, fbHeight);
|
||||
if (!xfbSource)
|
||||
{
|
||||
|
@ -1088,18 +1095,18 @@ void Renderer::SwapBuffers()
|
|||
}
|
||||
}
|
||||
#endif
|
||||
// Copy the rendered frame to the real window
|
||||
// Copy the rendered frame to the real window
|
||||
OpenGL_SwapBuffers();
|
||||
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
|
||||
// Clear framebuffer
|
||||
glClearColor(0, 0, 0, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
// Clean out old stuff from caches
|
||||
// Clean out old stuff from caches
|
||||
VertexShaderCache::ProgressiveCleanup();
|
||||
PixelShaderCache::ProgressiveCleanup();
|
||||
TextureMngr::ProgressiveCleanup();
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
#include "Fifo.h"
|
||||
|
||||
#include "Config.h"
|
||||
#include "Statistics.h"
|
||||
#include "MemoryUtil.h"
|
||||
|
@ -185,6 +187,11 @@ void Flush()
|
|||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
if(g_bSkipCurrentFrame) {
|
||||
ResetBuffer();
|
||||
return;
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, s_vboBuffers[s_nCurVBOIndex]);
|
||||
glBufferData(GL_ARRAY_BUFFER, s_pCurBufferPointer - s_pBaseBufferPointer, s_pBaseBufferPointer, GL_STREAM_DRAW);
|
||||
GL_REPORT_ERRORD();
|
||||
|
|
|
@ -448,6 +448,10 @@ void Video_AddMessage(const char* pstr, u32 milliseconds)
|
|||
OSD::AddMessage(pstr, milliseconds);
|
||||
}
|
||||
|
||||
void Video_SetRendering(bool bEnabled) {
|
||||
Fifo_SetRendering(bEnabled);
|
||||
}
|
||||
|
||||
static volatile struct
|
||||
{
|
||||
u32 xfbAddr;
|
||||
|
|
Loading…
Reference in New Issue