1. This should fix Issue 1625 (Bizarre Auto Frame Limit)

Now the frame limiter yields on CPU thread, not as before on GPU thread mistakenly

2. Fixed clear of VI interrupts
   I guess VI interrupts are not used at all, because they were never cleared before

3. Made GPU thread 0% processor usage when paused whatever your active config is.
   I tried the event approach but somehow the thread resume latency is excessively long (Who can tell me why?)

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4790 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
ayuanx 2010-01-07 20:01:41 +00:00
parent 64167bcb60
commit 9cbd508181
15 changed files with 141 additions and 227 deletions

View File

@ -78,7 +78,7 @@ void Timer::Update()
// -------------------------------------
// Get the number of milliseconds since the last Update()
s64 Timer::GetTimeDifference()
u64 Timer::GetTimeDifference()
{
return(timeGetTime() - m_LastTime);
}

View File

@ -36,7 +36,7 @@ public:
void Update();
// The time difference is always returned in milliseconds, regardless of alternative internal representation
s64 GetTimeDifference();
u64 GetTimeDifference();
void AddTimeDifference();
void WindBackStartingTime(u64 WindBack);

View File

@ -21,6 +21,7 @@
#endif
#include "Setup.h" // Common
#include "Atomic.h"
#include "Thread.h"
#include "Timer.h"
#include "Common.h"
@ -64,11 +65,9 @@
namespace Core
{
// Declarations and definitions
Common::Timer Timer;
u32 frames = 0;
volatile u32 DrawnFrame = 0;
// Function forwarding
//void Callback_VideoRequestWindowSize(int _iWidth, int _iHeight, BOOL _bFullscreen);
@ -587,102 +586,29 @@ void ScreenShot()
{
ScreenShot(GenerateScreenshotName());
}
// --- Callbacks for plugins / engine ---
// Callback_VideoLog
// WARNING - THIS IS EXECUTED FROM VIDEO THREAD
void Callback_VideoLog(const TCHAR *_szMessage, int _bDoBreak)
// Apply Frame Limit and Display FPS info
// This should only be called from VI
void FrameThrottle()
{
INFO_LOG(VIDEO, _szMessage);
}
// reports if a frame should be skipped or not
// depending on the framelimit set
bool report_slow(int skipped)
{
u32 targetfps = SConfig::GetInstance().m_Framelimit * 5;
double wait_frametime;
u32 TargetFPS = (SConfig::GetInstance().m_Framelimit > 1) ? SConfig::GetInstance().m_Framelimit * 5
: VideoInterface::TargetRefreshRate;
u32 frames = Common::AtomicLoad(DrawnFrame);
if (targetfps < 5)
wait_frametime = (1000.0 / VideoInterface::TargetRefreshRate);
else
wait_frametime = (1000.0 / targetfps);
bool fps_slow;
if (Timer.GetTimeDifference() < wait_frametime * (frames + skipped))
fps_slow=false;
else
fps_slow=true;
if (targetfps == 5)
fps_slow=true;
return fps_slow;
}
// Callback_VideoCopiedToXFB
// WARNING - THIS IS EXECUTED FROM VIDEO THREAD
// We do not write to anything outside this function here
void Callback_VideoCopiedToXFB(bool video_update)
{
if(!video_update)
Frame::FrameUpdate();
SCoreStartupParameter& _CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter;
//count FPS and VPS
static u32 videoupd = 0;
static u32 no_framelimit = 0;
if (video_update)
videoupd++;
else
frames++;
if (no_framelimit>0)
no_framelimit--;
// Custom frame limiter
// --------------------
u32 targetfps = SConfig::GetInstance().m_Framelimit * 5;
if (targetfps > 5)
// When frame limit is NOT off
if (frames && SConfig::GetInstance().m_Framelimit != 1)
{
double wait_frametime = (1000.0 / targetfps);
if (Timer.GetTimeDifference() >= wait_frametime * frames)
no_framelimit = (u32)Timer.GetTimeDifference();
while (Timer.GetTimeDifference() < wait_frametime * frames)
{
if (no_framelimit == 0)
Common::SleepCurrentThread(1);
}
}
else if (targetfps < 5)
{
double wait_frametime = (1000.0 / VideoInterface::TargetRefreshRate);
if (Timer.GetTimeDifference() >= wait_frametime * frames)
no_framelimit = (u32)Timer.GetTimeDifference();
while (Timer.GetTimeDifference() < wait_frametime * videoupd)
{
// TODO : This is wrong, the sleep shouldn't be there but rather in cputhread
// as it's not based on the fps but on the refresh rate...
if (no_framelimit == 0)
Common::SleepCurrentThread(1);
}
u32 frametime = frames * 1000 / TargetFPS;
while (Timer.GetTimeDifference() < frametime)
//Common::YieldCPU();
Common::SleepCurrentThread(1);
}
if (Timer.GetTimeDifference() >= 1000)
// Update info per second
u32 ElapseTime = (u32)Timer.GetTimeDifference();
if (ElapseTime >= 1000)
{
// Time passed
float t = (float)(Timer.GetTimeDifference()) / 1000.f;
SCoreStartupParameter& _CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter;
// Use extended or summary information. The summary information does not print the ticks data,
// that's more of a debugging interest, it can always be optional of course if someone is interested.
@ -691,8 +617,8 @@ void Callback_VideoCopiedToXFB(bool video_update)
u64 newTicks = CoreTiming::GetTicks();
u64 newIdleTicks = CoreTiming::GetIdleTicks();
s64 diff = (newTicks - ticks) / 1000000;
s64 idleDiff = (newIdleTicks - idleTicks) / 1000000;
u64 diff = (newTicks - ticks) / 1000000;
u64 idleDiff = (newIdleTicks - idleTicks) / 1000000;
ticks = newTicks;
idleTicks = newIdleTicks;
@ -700,13 +626,9 @@ void Callback_VideoCopiedToXFB(bool video_update)
float TicksPercentage = (float)diff / (float)(SystemTimers::GetTicksPerSecond() / 1000000) * 100;
#endif
float FPS = (float)frames / t;
// for some reasons "VideoInterface::ActualRefreshRate" gives some odd results :(
float VPS = (float)videoupd / t;
u32 FPS = frames * 1000 / ElapseTime;
int TargetVPS = (int)(VideoInterface::TargetRefreshRate + 0.5);
float Speed = ((VPS > 0.0f ? VPS : VideoInterface::ActualRefreshRate) / TargetVPS) * 100.0f;
float Speed = (float)FPS / (float)TargetFPS * 100.0f;
// Settings are shown the same for both extended and summary info
std::string SSettings = StringFromFormat(" | Core: %s %s",
@ -726,8 +648,7 @@ void Callback_VideoCopiedToXFB(bool video_update)
_CoreParameter.bCPUThread ? "DC" : "SC");
#ifdef EXTENDED_INFO
std::string SFPS = StringFromFormat("FPS: %4.1f - VPS: %i/%i (%3.0f%%)",
FPS, VPS > 0 ? (int)VPS : (int)VideoInterface::ActualRefreshRate, TargetVPS, Speed);
std::string SFPS = StringFromFormat("FPS: %i/%i (%3.0f%%)", FPS, TargetFPS, Speed);
SFPS += StringFromFormat(" | CPU: %s%i MHz [Real: %i + IdleSkip: %i] / %i MHz (%s%3.0f%%)",
_CoreParameter.bSkipIdle ? "~" : "",
(int)(diff),
@ -738,8 +659,7 @@ void Callback_VideoCopiedToXFB(bool video_update)
TicksPercentage);
#else // Summary information
std::string SFPS = StringFromFormat("FPS: %4.1f - VPS: %i/%i (%3.0f%%)",
FPS, VPS > 0 ? (int)VPS : (int)VideoInterface::ActualRefreshRate, TargetVPS, Speed);
std::string SFPS = StringFromFormat("FPS: %i/%i (%3.0f%%)", FPS, TargetFPS, Speed);
#endif
// This is our final "frame counter" string
@ -752,12 +672,39 @@ void Callback_VideoCopiedToXFB(bool video_update)
Host_UpdateStatusBar(SMessage.c_str());
// Reset frame counter
frames = 0;
videoupd = 0;
Timer.Update();
Common::AtomicStore(DrawnFrame, 0);
}
}
// Executed from GPU thread
// reports if a frame should be skipped or not
// depending on the framelimit set
bool report_slow(int skipped)
{
u32 TargetFPS = (SConfig::GetInstance().m_Framelimit > 1) ? SConfig::GetInstance().m_Framelimit * 5
: VideoInterface::TargetRefreshRate;
u32 frames = Common::AtomicLoad(DrawnFrame);
bool fps_slow = (Timer.GetTimeDifference() < (frames + skipped) * 1000 / TargetFPS) ? false : true;
return fps_slow;
}
// --- Callbacks for plugins / engine ---
// Callback_VideoLog
// WARNING - THIS IS EXECUTED FROM VIDEO THREAD
void Callback_VideoLog(const TCHAR *_szMessage, int _bDoBreak)
{
INFO_LOG(VIDEO, _szMessage);
}
// Should be called from GPU thread when a frame is drawn
void Callback_VideoCopiedToXFB(bool video_update)
{
Common::AtomicIncrement(DrawnFrame);
Frame::FrameUpdate();
}
// Callback_DSPLog
// WARNING - THIS MAY BE EXECUTED FROM DSP THREAD
@ -835,7 +782,8 @@ void Callback_WiimoteLog(const TCHAR* _szMessage, int _v)
}
// TODO: Get rid of at some point
const SCoreStartupParameter& GetStartupParameter() {
const SCoreStartupParameter& GetStartupParameter()
{
return SConfig::GetInstance().m_LocalCoreStartupParameter;
}

View File

@ -74,6 +74,7 @@ namespace Core
void StopTrace();
bool report_slow(int skipped);
void FrameThrottle();
// -----------------------------------------
#ifdef RERECORDING

View File

@ -19,8 +19,7 @@
#include "ChunkFile.h"
#include "../PowerPC/PowerPC.h"
#include "../Core.h" // <- for Core::GetStartupParameter().bUseDualCore
#include "../Core.h"
#include "ProcessorInterface.h"
#include "VideoInterface.h"
#include "Memmap.h"
@ -28,7 +27,6 @@
#include "../CoreTiming.h"
#include "../HW/SystemTimers.h"
#include "StringUtil.h"
#include "Timer.h"
namespace VideoInterface
{
@ -53,7 +51,7 @@ enum
VI_FB_LEFT_TOP_LO = 0x1e,
VI_FB_RIGHT_TOP_HI = 0x20, // FB_RIGHT_TOP is only used in 3D mode
VI_FB_RIGHT_TOP_LO = 0x22,
VI_FB_LEFT_BOTTOM_HI = 0x24, // FB_LEFT_TOP is second half of XFB info
VI_FB_LEFT_BOTTOM_HI = 0x24, // FB_LEFT_BOTTOM is second half of XFB info
VI_FB_LEFT_BOTTOM_LO = 0x26,
VI_FB_RIGHT_BOTTOM_HI = 0x28, // FB_RIGHT_BOTTOM is only used in 3D mode
VI_FB_RIGHT_BOTTOM_LO = 0x2a,
@ -268,6 +266,7 @@ union UVIFilterCoefTable3
unsigned : 2;
};
};
// Used for tables 3-6
union UVIFilterCoefTable4
{
@ -281,6 +280,7 @@ union UVIFilterCoefTable4
unsigned Tap3 : 8;
};
};
struct SVIFilterCoefTables
{
UVIFilterCoefTable3 Tables02[3];
@ -331,16 +331,13 @@ static UVIBorderBlankRegister m_BorderHBlank;
// 0xcc002076 - 0xcc00207f is full of 0x00FF: unknown
// 0xcc002080 - 0xcc002100 even more unknown
u32 TargetRefreshRate = 0;
static u32 TicksPerFrame = 0;
static u32 s_lineCount = 0;
static u32 s_upperFieldBegin = 0;
static u32 s_lowerFieldBegin = 0;
float TargetRefreshRate = 0.0;
float ActualRefreshRate = 0.0;
s64 SyncTicksProgress = 0;
void DoState(PointerWrap &p)
{
p.Do(m_VerticalTimingRegister);
@ -367,7 +364,7 @@ void DoState(PointerWrap &p)
p.Do(m_DTVStatus);
p.Do(m_FBWidth);
p.Do(m_BorderHBlank);
p.Do(TargetRefreshRate);
p.Do(TicksPerFrame);
p.Do(s_lineCount);
p.Do(s_upperFieldBegin);
@ -376,11 +373,6 @@ void DoState(PointerWrap &p)
void PreInit(bool _bNTSC)
{
TicksPerFrame = 0;
s_lineCount = 0;
s_upperFieldBegin = 0;
s_lowerFieldBegin = 0;
m_VerticalTimingRegister.EQU = 6;
m_DisplayControlRegister.ENB = 1;
@ -439,9 +431,7 @@ void Init()
m_DisplayControlRegister.Hex = 0;
s_lineCount = 0;
s_upperFieldBegin = 0;
s_lowerFieldBegin = 0;
UpdateTiming();
}
void Read8(u8& _uReturnValue, const u32 _iAddress)
@ -711,9 +701,12 @@ void Write16(const u16 _iValue, const u32 _iAddress)
{
// shuffle2 clear all data, reset to default vals, and enter idle mode
m_DisplayControlRegister.RST = 0;
for (int i = 0; i < 4; i++)
m_InterruptRegister[i].Hex = 0;
UpdateInterrupts();
}
UpdateTiming();
UpdateTiming();
}
break;
@ -802,38 +795,38 @@ void Write16(const u16 _iValue, const u32 _iAddress)
// RETRACE STUFF ...
case VI_PRERETRACE_HI:
m_InterruptRegister[0].Hi = _iValue;
m_InterruptRegister[0].IR_INT = 0;
UpdateInterrupts();
break;
case VI_PRERETRACE_LO:
m_InterruptRegister[0].Lo = _iValue;
UpdateInterrupts();
break;
case VI_POSTRETRACE_HI:
m_InterruptRegister[1].Hi = _iValue;
m_InterruptRegister[1].IR_INT = 0;
UpdateInterrupts();
break;
case VI_POSTRETRACE_LO:
m_InterruptRegister[1].Lo = _iValue;
UpdateInterrupts();
break;
case VI_DISPLAY_INTERRUPT_2_HI:
m_InterruptRegister[2].Hi = _iValue;
m_InterruptRegister[2].IR_INT = 0;
UpdateInterrupts();
break;
case VI_DISPLAY_INTERRUPT_2_LO:
m_InterruptRegister[2].Lo = _iValue;
UpdateInterrupts();
break;
case VI_DISPLAY_INTERRUPT_3_HI:
m_InterruptRegister[3].Hi = _iValue;
m_InterruptRegister[3].IR_INT = 0;
UpdateInterrupts();
break;
case VI_DISPLAY_INTERRUPT_3_LO:
m_InterruptRegister[3].Lo = _iValue;
UpdateInterrupts();
break;
case VI_DISPLAY_LATCH_0_HI:
@ -988,46 +981,22 @@ u32 GetXFBAddressBottom()
return m_XFBInfoBottom.FBB;
}
// NTSC is 60 FPS, right?
// Wrong, it's about 59.94 FPS. The NTSC engineers had to slightly lower
// the field rate from 60 FPS when they added color to the standard.
// This was done to prevent analog interference between the video and
// audio signals. PAL has no similar reduction; it is exactly 50 FPS.
const double NTSC_FIELD_RATE = 60.0 / 1.001;
const u32 NTSC_LINE_COUNT = 525;
// These line numbers indicate the beginning of the "active video" in a frame.
// An NTSC frame has the lower field first followed by the upper field.
// TODO: Is this true for PAL-M? Is this true for EURGB60?
const u32 NTSC_LOWER_BEGIN = 21;
const u32 NTSC_UPPER_BEGIN = 283;
const double PAL_FIELD_RATE = 50.0;
const u32 PAL_LINE_COUNT = 625;
// These line numbers indicate the beginning of the "active video" in a frame.
// A PAL frame has the upper field first followed by the lower field.
const u32 PAL_UPPER_BEGIN = 23; // TODO: Actually 23.5!
const u32 PAL_LOWER_BEGIN = 336;
// Screenshot and screen message
void UpdateTiming()
{
switch (m_DisplayControlRegister.FMT)
{
case 0: // NTSC
case 2: // PAL-M
TicksPerFrame = (u32)(SystemTimers::GetTicksPerSecond() / (NTSC_FIELD_RATE / 2.0));
TargetRefreshRate = NTSC_FIELD_RATE;
TicksPerFrame = SystemTimers::GetTicksPerSecond() / (NTSC_FIELD_RATE / 2);
s_lineCount = m_DisplayControlRegister.NIN ? (NTSC_LINE_COUNT+1)/2 : NTSC_LINE_COUNT;
// TODO: The game may have some control over these parameters (not that it's useful).
s_upperFieldBegin = NTSC_UPPER_BEGIN;
s_lowerFieldBegin = NTSC_LOWER_BEGIN;
break;
case 1: // PAL
TicksPerFrame = (u32)(SystemTimers::GetTicksPerSecond() / (PAL_FIELD_RATE / 2.0));
TargetRefreshRate = PAL_FIELD_RATE;
TicksPerFrame = SystemTimers::GetTicksPerSecond() / (PAL_FIELD_RATE / 2);
s_lineCount = m_DisplayControlRegister.NIN ? (PAL_LINE_COUNT+1)/2 : PAL_LINE_COUNT;
s_upperFieldBegin = PAL_UPPER_BEGIN;
s_lowerFieldBegin = PAL_LOWER_BEGIN;
@ -1040,7 +1009,6 @@ void UpdateTiming()
default:
PanicAlert("Unknown Video Format - CVideoInterface");
break;
}
}
@ -1056,7 +1024,6 @@ int GetTicksPerFrame()
return TicksPerFrame;
}
static void BeginField(FieldType field)
{
u32 fbWidth = m_HorizontalStepping.FieldSteps * 16;
@ -1088,45 +1055,24 @@ static void EndField()
}
// Purpose 1: Send VI interrupt for every screen refresh
// Purpose 2: Execute XFB copy in homebrew games
// Run when: This is run 15700 times per second on full speed
// Purpose: Send VI interrupt when triggered
// Run when: When every line is scaned
void Update()
{
// Update the target refresh rate
TargetRefreshRate = (float)((m_DisplayControlRegister.FMT == 0 || m_DisplayControlRegister.FMT == 2)
? NTSC_FIELD_RATE : PAL_FIELD_RATE);
// Calculate actual refresh rate
static u64 LastTick = 0;
static s64 UpdateCheck = timeGetTime() + 1000, TickProgress = 0;
s64 curTime = timeGetTime();
if (UpdateCheck < (int)curTime)
{
UpdateCheck = curTime + 1000;
TickProgress = CoreTiming::GetTicks() - LastTick;
// Calculated CPU-GPU synced ticks for the dual core mode too
// NOTICE_LOG(VIDEO, "Removed: %s Mhz", ThS(SyncTicksProgress / 1000000, false).c_str());
SyncTicksProgress += TickProgress;
// Multipled by two because of the way TicksPerFrame is calculated (divided by 25 and 30
// rather than 50 and 60)
ActualRefreshRate = (float)(((double)SyncTicksProgress / (double)TicksPerFrame) * 2.0);
LastTick = CoreTiming::GetTicks();
SyncTicksProgress = 0;
}
// TODO: What's the correct behavior for progressive mode?
if (m_VBeamPos == s_upperFieldBegin + m_VerticalTimingRegister.ACV)
EndField();
if (m_VBeamPos == s_lowerFieldBegin + m_VerticalTimingRegister.ACV)
else if (m_VBeamPos == s_lowerFieldBegin + m_VerticalTimingRegister.ACV)
EndField();
m_VBeamPos++;
if (m_VBeamPos > s_lineCount)
if (++m_VBeamPos > s_lineCount)
{
m_VBeamPos = 1;
// Apply frame throttle wheneven a full screen scan finishes
Core::FrameThrottle();
}
for (int i = 0; i < 4; ++i)
{
@ -1135,11 +1081,12 @@ void Update()
}
UpdateInterrupts();
if (m_VBeamPos == s_upperFieldBegin)
BeginField(m_DisplayControlRegister.NIN ? FIELD_PROGRESSIVE : FIELD_UPPER);
if (m_VBeamPos == s_lowerFieldBegin)
else if (m_VBeamPos == s_lowerFieldBegin)
BeginField(m_DisplayControlRegister.NIN ? FIELD_PROGRESSIVE : FIELD_LOWER);
}
} // namespace

View File

@ -22,6 +22,31 @@ class PointerWrap;
namespace VideoInterface
{
// NTSC is 60 FPS, right?
// Wrong, it's about 59.94 FPS. The NTSC engineers had to slightly lower
// the field rate from 60 FPS when they added color to the standard.
// This was done to prevent analog interference between the video and
// audio signals. PAL has no similar reduction; it is exactly 50 FPS.
//#define NTSC_FIELD_RATE (60.0f / 1.001f)
#define NTSC_FIELD_RATE 60
#define NTSC_LINE_COUNT 525
// These line numbers indicate the beginning of the "active video" in a frame.
// An NTSC frame has the lower field first followed by the upper field.
// TODO: Is this true for PAL-M? Is this true for EURGB60?
#define NTSC_LOWER_BEGIN 21
#define NTSC_UPPER_BEGIN 283
//#define PAL_FIELD_RATE 50.0f
#define PAL_FIELD_RATE 50
#define PAL_LINE_COUNT 625
// These line numbers indicate the beginning of the "active video" in a frame.
// A PAL frame has the upper field first followed by the lower field.
#define PAL_UPPER_BEGIN 23 // TODO: Actually 23.5!
#define PAL_LOWER_BEGIN 336
// urgh, ugly externs.
extern u32 TargetRefreshRate;
// For BS2 HLE
void PreInit(bool _bNTSC);
void SetRegionReg(char _region);
@ -43,11 +68,6 @@ namespace VideoInterface
// Update and draw framebuffer(s)
void Update();
// urgh, ugly externs.
extern float ActualRefreshRate;
extern float TargetRefreshRate;
extern s64 SyncTicksProgress;
// UpdateInterrupts: check if we have to generate a new VI Interrupt
void UpdateInterrupts();

View File

@ -32,7 +32,7 @@ u32 g_autoFirstKey = 0, g_autoSecondKey = 0;
bool g_bFirstKey = true;
PlayMode g_playMode = MODE_NONE;
int g_framesToSkip = 0, g_frameSkipCounter = 0;
unsigned int g_framesToSkip = 0, g_frameSkipCounter = 0;
int g_numPads = 0;
ControllerState *g_padStates;
@ -70,14 +70,13 @@ void FrameUpdate() {
EndPlayInput();
}
g_bPolled = false;
}
void SetFrameSkipping(unsigned int framesToSkip) {
cs_frameSkip.Enter();
g_framesToSkip = (int)framesToSkip;
g_framesToSkip = framesToSkip;
g_frameSkipCounter = 0;
// Don't forget to re-enable rendering in case it wasn't...

View File

@ -51,7 +51,9 @@ extern bool g_bFrameStep, g_bAutoFire, g_bFirstKey, g_bPolled;
extern u32 g_autoFirstKey, g_autoSecondKey;
extern PlayMode g_playMode;
extern int g_framesToSkip, g_frameSkipCounter, g_numPads;
extern unsigned int g_framesToSkip, g_frameSkipCounter;
extern int g_numPads;
extern ControllerState *g_padStates;
extern FILE *g_recordfd;
extern std::string g_recordFile;

View File

@ -383,7 +383,6 @@ void Write16(const u16 _Value, const u32 _Address)
// Touching that game is a no-go so I don't want to take the risk :p
while (fifo.bFF_GPReadEnable && ((!fifo.bFF_BPEnable && fifo.CPReadWriteDistance) || (fifo.bFF_BPEnable && !fifo.bFF_Breakpoint)))
{
Fifo_RunLoop();
s_fifoIdleEvent.MsgWait();
}
}
@ -414,8 +413,6 @@ void Write16(const u16 _Value, const u32 _Address)
Common::AtomicStore(fifo.bFF_Breakpoint, 0);
}
Fifo_RunLoop();
DEBUG_LOG(COMMANDPROCESSOR,"\t write to CTRL_REGISTER : %04x", _Value);
DEBUG_LOG(COMMANDPROCESSOR, "\t GPREAD %s | LINK %s | BP %s || Init %s | OvF %s | UndF %s"
, fifo.bFF_GPReadEnable ? "ON" : "OFF"
@ -572,10 +569,9 @@ void WaitForFrameFinish()
{
while ((fake_GPWatchdogLastToken == fifo.Fake_GPWDToken) && fifo.bFF_GPReadEnable && ((!fifo.bFF_BPEnable && fifo.CPReadWriteDistance) || (fifo.bFF_BPEnable && !fifo.bFF_Breakpoint)));
{
Fifo_RunLoop();
s_fifoIdleEvent.MsgWait();
}
fake_GPWatchdogLastToken = fifo.Fake_GPWDToken;
}
@ -594,7 +590,6 @@ void STACKALIGN GatherPipeBursted()
fifo.CPWritePointer += GATHER_PIPE_SIZE;
Common::AtomicAdd(fifo.CPReadWriteDistance, GATHER_PIPE_SIZE);
Fifo_RunLoop();
// High watermark overflow handling (hacked way)
if (fifo.CPReadWriteDistance > fifo.CPHiWatermark)
@ -619,7 +614,6 @@ void STACKALIGN GatherPipeBursted()
// Wait for GPU to catch up
while (fifo.CPReadWriteDistance > fifo.CPLoWatermark && fifo.bFF_GPReadEnable && (!fifo.bFF_BPEnable || (fifo.bFF_BPEnable && !fifo.bFF_Breakpoint)))
{
Fifo_RunLoop();
s_fifoIdleEvent.MsgWait();
}
}
@ -725,7 +719,6 @@ void UpdateFifoRegister()
dist = (wp - fifo.CPBase) + ((fifo.CPEnd + GATHER_PIPE_SIZE) - rp);
Common::AtomicStore(fifo.CPReadWriteDistance, dist);
Fifo_RunLoop();
if (!g_VideoInitialize.bOnThread)
CatchUpGPU();

View File

@ -34,6 +34,7 @@ extern u8* g_pVideoData;
namespace
{
static volatile bool fifoStateRun = false;
static volatile bool EmuRunning = false;
static u8 *videoBuffer;
static Common::Event fifo_run_event;
// STATE_TO_SAVE
@ -100,9 +101,11 @@ void Fifo_ExitLoopNonBlocking()
fifo_run_event.Set();
}
void Fifo_RunLoop()
void Fifo_RunLoop(bool run)
{
fifo_run_event.Set();
EmuRunning = run;
if (run)
fifo_run_event.Set();
}
// Description: Fifo_EnterLoop() sends data through this function.
@ -210,9 +213,7 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize)
}
CommandProcessor::SetFifoIdleFromVideoPlugin();
// "VideoFifo_CheckEFBAccess()" & "VideoFifo_CheckSwapRequest()" should be
// moved to a more suitable place than inside function "Fifo_EnterLoop()"
if (g_ActiveConfig.bEFBAccessEnable || g_ActiveConfig.bUseXFB)
if (EmuRunning)
Common::YieldCPU();
else
fifo_run_event.MsgWait();

View File

@ -36,7 +36,7 @@ void Fifo_SendFifoData(u8* _uData, u32 len);
void Fifo_EnterLoop(const SVideoInitialize &video_initialize);
void Fifo_ExitLoop();
void Fifo_ExitLoopNonBlocking();
void Fifo_RunLoop();
void Fifo_RunLoop(bool run);
void Fifo_DoState(PointerWrap &f);

View File

@ -535,6 +535,7 @@ void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRect
DEBUGGER_PAUSE_LOG_AT(NEXT_XFB_CMD,false,{printf("RenderToXFB - disabled");});
return;
}
Renderer::ResetAPIState();
// Set the backbuffer as the rendering target
D3D::dev->SetDepthStencilSurface(NULL);
@ -543,7 +544,6 @@ void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRect
D3DDumpFrame();
EFBTextureToD3DBackBuffer(sourceRc);
D3D::EndFrame();
DEBUGGER_LOG_AT((NEXT_XFB_CMD|NEXT_EFB_CMD|NEXT_FRAME),
{printf("StretchRect, EFB->XFB\n");});
@ -553,6 +553,7 @@ void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRect
xfbAddr, fbWidth, fbHeight,
sourceRc.left, sourceRc.top, sourceRc.right, sourceRc.bottom);}
);
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
D3D::BeginFrame();
@ -959,9 +960,9 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
// Make any new configuration settings active.
UpdateActiveConfig();
//TODO: Resize backbuffer if window size has changed. This code crashes, debug it.
g_VideoInitialize.pCopiedToXFB(false);
//TODO: Resize backbuffer if window size has changed. This code crashes, debug it.
CheckForResize();
// ---------------------------------------------------------------------

View File

@ -312,6 +312,7 @@ void DoState(unsigned char **ptr, int mode) {
void EmuStateChange(PLUGIN_EMUSTATE newState)
{
Fifo_RunLoop((newState == PLUGIN_EMUSTATE_PLAY) ? true : false);
}
void Video_EnterLoop()
@ -333,7 +334,7 @@ void Video_SetRendering(bool bEnabled) {
// Run from the graphics thread
void VideoFifo_CheckSwapRequest()
{
// CPU swap, not finished, seems to be working fine for dual-core for now
// swap unimplemented
return;
if (s_swapRequested)
@ -351,12 +352,15 @@ void VideoFifo_CheckSwapRequest()
// Run from the graphics thread
void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight)
{
// CPU swap unimplemented
// swap unimplemented
}
// Run from the CPU thread (from VideoInterface.cpp)
void Video_BeginField(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
{
// swap unimplemented
return;
s_beginFieldArgs.xfbAddr = xfbAddr;
s_beginFieldArgs.field = field;
s_beginFieldArgs.fbWidth = fbWidth;
@ -365,14 +369,11 @@ void Video_BeginField(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
if (s_initialized)
{
// Make sure previous swap request has made it to the screen
if (g_VideoInitialize.bOnThread)
{
// 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();
//Common::YieldCPU();
}
else
VideoFifo_CheckSwapRequest();

View File

@ -597,6 +597,9 @@ void Renderer::SetBlendMode(bool forceUpdate)
u32 Renderer::AccessEFB(EFBAccessType type, int x, int y)
{
if(!g_ActiveConfig.bEFBAccessEnable)
return 0;
// Get the rectangular target region covered by the EFB pixel.
EFBRectangle efbPixelRc;
efbPixelRc.left = x;

View File

@ -379,6 +379,7 @@ void DoState(unsigned char **ptr, int mode) {
void EmuStateChange(PLUGIN_EMUSTATE newState)
{
Fifo_RunLoop((newState == PLUGIN_EMUSTATE_PLAY) ? true : false);
}
// This is called after Video_Initialize() from the Core
@ -494,9 +495,6 @@ void VideoFifo_CheckSwapRequest()
g_VideoInitialize.pCopiedToXFB(false);
}
// TODO : This just updates the frame counter, so we may change this func's name as well
g_VideoInitialize.pCopiedToXFB(true);
Common::AtomicStoreRelease(s_swapRequested, FALSE);
}
}