Merge pull request #10244 from phire/ban-timetravel

Delay singlecore gpu interrupts; Fixes Bomberman Jetters in single core mode.
This commit is contained in:
JMC47 2021-12-02 07:21:41 -05:00 committed by GitHub
commit c12e4e8ee0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 29 additions and 22 deletions

View File

@ -2205,7 +2205,7 @@ struct BPMemory
extern BPMemory bpmem;
void LoadBPReg(u32 value0);
void LoadBPRegPreprocess(u32 value0);
void LoadBPReg(u32 value0, int cycles_into_future);
void LoadBPRegPreprocess(u32 value0, int cycles_into_future);
std::pair<std::string, std::string> GetBPRegInfo(u8 cmd, u32 cmddata);

View File

@ -50,7 +50,7 @@ void BPInit()
bpmem.bpMask = 0xFFFFFF;
}
static void BPWritten(const BPCmd& bp)
static void BPWritten(const BPCmd& bp, int cycles_into_future)
{
/*
----------------------------------------------------------------------------------------------------------------
@ -180,7 +180,7 @@ static void BPWritten(const BPCmd& bp)
g_texture_cache->FlushEFBCopies();
g_framebuffer_manager->InvalidatePeekCache(false);
if (!Fifo::UseDeterministicGPUThread())
PixelEngine::SetFinish(); // may generate interrupt
PixelEngine::SetFinish(cycles_into_future); // may generate interrupt
DEBUG_LOG_FMT(VIDEO, "GXSetDrawDone SetPEFinish (value: {:#04X})", bp.newvalue & 0xFFFF);
return;
@ -193,14 +193,14 @@ static void BPWritten(const BPCmd& bp)
g_texture_cache->FlushEFBCopies();
g_framebuffer_manager->InvalidatePeekCache(false);
if (!Fifo::UseDeterministicGPUThread())
PixelEngine::SetToken(static_cast<u16>(bp.newvalue & 0xFFFF), false);
PixelEngine::SetToken(static_cast<u16>(bp.newvalue & 0xFFFF), false, cycles_into_future);
DEBUG_LOG_FMT(VIDEO, "SetPEToken {:#06X}", bp.newvalue & 0xFFFF);
return;
case BPMEM_PE_TOKEN_INT_ID: // Pixel Engine Interrupt Token ID
g_texture_cache->FlushEFBCopies();
g_framebuffer_manager->InvalidatePeekCache(false);
if (!Fifo::UseDeterministicGPUThread())
PixelEngine::SetToken(static_cast<u16>(bp.newvalue & 0xFFFF), true);
PixelEngine::SetToken(static_cast<u16>(bp.newvalue & 0xFFFF), true, cycles_into_future);
DEBUG_LOG_FMT(VIDEO, "SetPEToken + INT {:#06X}", bp.newvalue & 0xFFFF);
return;
@ -717,7 +717,7 @@ static void BPWritten(const BPCmd& bp)
}
// Call browser: OpcodeDecoding.cpp ExecuteDisplayList > Decode() > LoadBPReg()
void LoadBPReg(u32 value0)
void LoadBPReg(u32 value0, int cycles_into_future)
{
int regNum = value0 >> 24;
int oldval = ((u32*)&bpmem)[regNum];
@ -730,10 +730,10 @@ void LoadBPReg(u32 value0)
if (regNum != BPMEM_BP_MASK)
bpmem.bpMask = 0xFFFFFF;
BPWritten(bp);
BPWritten(bp, cycles_into_future);
}
void LoadBPRegPreprocess(u32 value0)
void LoadBPRegPreprocess(u32 value0, int cycles_into_future)
{
int regNum = value0 >> 24;
// masking could hypothetically be a problem
@ -742,13 +742,13 @@ void LoadBPRegPreprocess(u32 value0)
{
case BPMEM_SETDRAWDONE:
if ((newval & 0xff) == 0x02)
PixelEngine::SetFinish();
PixelEngine::SetFinish(cycles_into_future);
break;
case BPMEM_PE_TOKEN_ID:
PixelEngine::SetToken(newval & 0xffff, false);
PixelEngine::SetToken(newval & 0xffff, false, cycles_into_future);
break;
case BPMEM_PE_TOKEN_INT_ID: // Pixel Engine Interrupt Token ID
PixelEngine::SetToken(newval & 0xffff, true);
PixelEngine::SetToken(newval & 0xffff, true, cycles_into_future);
break;
}
}

View File

@ -221,11 +221,11 @@ u8* Run(DataReader src, u32* cycles, bool in_display_list)
const u32 bp_cmd = src.Read<u32>();
if constexpr (is_preprocess)
{
LoadBPRegPreprocess(bp_cmd);
LoadBPRegPreprocess(bp_cmd, total_cycles);
}
else
{
LoadBPReg(bp_cmd);
LoadBPReg(bp_cmd, total_cycles);
INCSTAT(g_stats.this_frame.num_bp_loads);
}
}

View File

@ -277,7 +277,7 @@ static void SetTokenFinish_OnMainThread(u64 userdata, s64 cyclesLate)
// Raise the event handler above on the CPU thread.
// s_token_finish_mutex must be locked.
// THIS IS EXECUTED FROM VIDEO THREAD
static void RaiseEvent()
static void RaiseEvent(int cycles_into_future)
{
if (s_event_raised)
return;
@ -285,14 +285,21 @@ static void RaiseEvent()
s_event_raised = true;
CoreTiming::FromThread from = CoreTiming::FromThread::NON_CPU;
s64 cycles = 0; // we don't care about timings for dual core mode.
if (!SConfig::GetInstance().bCPUThread || Fifo::UseDeterministicGPUThread())
{
from = CoreTiming::FromThread::CPU;
CoreTiming::ScheduleEvent(0, et_SetTokenFinishOnMainThread, 0, from);
// Hack: Dolphin's single-core gpu timings are way too fast. Enforce a minimum delay to give
// games time to setup any interrupt state
cycles = std::max(500, cycles_into_future);
}
CoreTiming::ScheduleEvent(cycles, et_SetTokenFinishOnMainThread, 0, from);
}
// SetToken
// THIS IS EXECUTED FROM VIDEO THREAD
void SetToken(const u16 token, const bool interrupt)
void SetToken(const u16 token, const bool interrupt, int cycles_into_future)
{
DEBUG_LOG_FMT(PIXELENGINE, "VIDEO Backend raises INT_CAUSE_PE_TOKEN (btw, token: {:04x})", token);
@ -301,12 +308,12 @@ void SetToken(const u16 token, const bool interrupt)
s_token_pending = token;
s_token_interrupt_pending |= interrupt;
RaiseEvent();
RaiseEvent(cycles_into_future);
}
// SetFinish
// THIS IS EXECUTED FROM VIDEO THREAD (BPStructs.cpp) when a new frame has been drawn
void SetFinish()
void SetFinish(int cycles_into_future)
{
DEBUG_LOG_FMT(PIXELENGINE, "VIDEO Set Finish");
@ -314,7 +321,7 @@ void SetFinish()
s_finish_interrupt_pending |= true;
RaiseEvent();
RaiseEvent(cycles_into_future);
}
UPEAlphaReadReg GetAlphaReadMode()

View File

@ -61,8 +61,8 @@ void DoState(PointerWrap& p);
void RegisterMMIO(MMIO::Mapping* mmio, u32 base);
// gfx backend support
void SetToken(const u16 token, const bool interrupt);
void SetFinish();
void SetToken(const u16 token, const bool interrupt, int cycle_delay);
void SetFinish(int cycle_delay);
UPEAlphaReadReg GetAlphaReadMode();
} // namespace PixelEngine