Merge pull request #10244 from phire/ban-timetravel
Delay singlecore gpu interrupts; Fixes Bomberman Jetters in single core mode.
This commit is contained in:
commit
c12e4e8ee0
|
@ -2205,7 +2205,7 @@ struct BPMemory
|
||||||
|
|
||||||
extern BPMemory bpmem;
|
extern BPMemory bpmem;
|
||||||
|
|
||||||
void LoadBPReg(u32 value0);
|
void LoadBPReg(u32 value0, int cycles_into_future);
|
||||||
void LoadBPRegPreprocess(u32 value0);
|
void LoadBPRegPreprocess(u32 value0, int cycles_into_future);
|
||||||
|
|
||||||
std::pair<std::string, std::string> GetBPRegInfo(u8 cmd, u32 cmddata);
|
std::pair<std::string, std::string> GetBPRegInfo(u8 cmd, u32 cmddata);
|
||||||
|
|
|
@ -50,7 +50,7 @@ void BPInit()
|
||||||
bpmem.bpMask = 0xFFFFFF;
|
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_texture_cache->FlushEFBCopies();
|
||||||
g_framebuffer_manager->InvalidatePeekCache(false);
|
g_framebuffer_manager->InvalidatePeekCache(false);
|
||||||
if (!Fifo::UseDeterministicGPUThread())
|
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);
|
DEBUG_LOG_FMT(VIDEO, "GXSetDrawDone SetPEFinish (value: {:#04X})", bp.newvalue & 0xFFFF);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -193,14 +193,14 @@ static void BPWritten(const BPCmd& bp)
|
||||||
g_texture_cache->FlushEFBCopies();
|
g_texture_cache->FlushEFBCopies();
|
||||||
g_framebuffer_manager->InvalidatePeekCache(false);
|
g_framebuffer_manager->InvalidatePeekCache(false);
|
||||||
if (!Fifo::UseDeterministicGPUThread())
|
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);
|
DEBUG_LOG_FMT(VIDEO, "SetPEToken {:#06X}", bp.newvalue & 0xFFFF);
|
||||||
return;
|
return;
|
||||||
case BPMEM_PE_TOKEN_INT_ID: // Pixel Engine Interrupt Token ID
|
case BPMEM_PE_TOKEN_INT_ID: // Pixel Engine Interrupt Token ID
|
||||||
g_texture_cache->FlushEFBCopies();
|
g_texture_cache->FlushEFBCopies();
|
||||||
g_framebuffer_manager->InvalidatePeekCache(false);
|
g_framebuffer_manager->InvalidatePeekCache(false);
|
||||||
if (!Fifo::UseDeterministicGPUThread())
|
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);
|
DEBUG_LOG_FMT(VIDEO, "SetPEToken + INT {:#06X}", bp.newvalue & 0xFFFF);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -717,7 +717,7 @@ static void BPWritten(const BPCmd& bp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call browser: OpcodeDecoding.cpp ExecuteDisplayList > Decode() > LoadBPReg()
|
// Call browser: OpcodeDecoding.cpp ExecuteDisplayList > Decode() > LoadBPReg()
|
||||||
void LoadBPReg(u32 value0)
|
void LoadBPReg(u32 value0, int cycles_into_future)
|
||||||
{
|
{
|
||||||
int regNum = value0 >> 24;
|
int regNum = value0 >> 24;
|
||||||
int oldval = ((u32*)&bpmem)[regNum];
|
int oldval = ((u32*)&bpmem)[regNum];
|
||||||
|
@ -730,10 +730,10 @@ void LoadBPReg(u32 value0)
|
||||||
if (regNum != BPMEM_BP_MASK)
|
if (regNum != BPMEM_BP_MASK)
|
||||||
bpmem.bpMask = 0xFFFFFF;
|
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;
|
int regNum = value0 >> 24;
|
||||||
// masking could hypothetically be a problem
|
// masking could hypothetically be a problem
|
||||||
|
@ -742,13 +742,13 @@ void LoadBPRegPreprocess(u32 value0)
|
||||||
{
|
{
|
||||||
case BPMEM_SETDRAWDONE:
|
case BPMEM_SETDRAWDONE:
|
||||||
if ((newval & 0xff) == 0x02)
|
if ((newval & 0xff) == 0x02)
|
||||||
PixelEngine::SetFinish();
|
PixelEngine::SetFinish(cycles_into_future);
|
||||||
break;
|
break;
|
||||||
case BPMEM_PE_TOKEN_ID:
|
case BPMEM_PE_TOKEN_ID:
|
||||||
PixelEngine::SetToken(newval & 0xffff, false);
|
PixelEngine::SetToken(newval & 0xffff, false, cycles_into_future);
|
||||||
break;
|
break;
|
||||||
case BPMEM_PE_TOKEN_INT_ID: // Pixel Engine Interrupt Token ID
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -221,11 +221,11 @@ u8* Run(DataReader src, u32* cycles, bool in_display_list)
|
||||||
const u32 bp_cmd = src.Read<u32>();
|
const u32 bp_cmd = src.Read<u32>();
|
||||||
if constexpr (is_preprocess)
|
if constexpr (is_preprocess)
|
||||||
{
|
{
|
||||||
LoadBPRegPreprocess(bp_cmd);
|
LoadBPRegPreprocess(bp_cmd, total_cycles);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LoadBPReg(bp_cmd);
|
LoadBPReg(bp_cmd, total_cycles);
|
||||||
INCSTAT(g_stats.this_frame.num_bp_loads);
|
INCSTAT(g_stats.this_frame.num_bp_loads);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -277,7 +277,7 @@ static void SetTokenFinish_OnMainThread(u64 userdata, s64 cyclesLate)
|
||||||
// Raise the event handler above on the CPU thread.
|
// Raise the event handler above on the CPU thread.
|
||||||
// s_token_finish_mutex must be locked.
|
// s_token_finish_mutex must be locked.
|
||||||
// THIS IS EXECUTED FROM VIDEO THREAD
|
// THIS IS EXECUTED FROM VIDEO THREAD
|
||||||
static void RaiseEvent()
|
static void RaiseEvent(int cycles_into_future)
|
||||||
{
|
{
|
||||||
if (s_event_raised)
|
if (s_event_raised)
|
||||||
return;
|
return;
|
||||||
|
@ -285,14 +285,21 @@ static void RaiseEvent()
|
||||||
s_event_raised = true;
|
s_event_raised = true;
|
||||||
|
|
||||||
CoreTiming::FromThread from = CoreTiming::FromThread::NON_CPU;
|
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())
|
if (!SConfig::GetInstance().bCPUThread || Fifo::UseDeterministicGPUThread())
|
||||||
|
{
|
||||||
from = CoreTiming::FromThread::CPU;
|
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
|
// SetToken
|
||||||
// THIS IS EXECUTED FROM VIDEO THREAD
|
// 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);
|
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_pending = token;
|
||||||
s_token_interrupt_pending |= interrupt;
|
s_token_interrupt_pending |= interrupt;
|
||||||
|
|
||||||
RaiseEvent();
|
RaiseEvent(cycles_into_future);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetFinish
|
// SetFinish
|
||||||
// THIS IS EXECUTED FROM VIDEO THREAD (BPStructs.cpp) when a new frame has been drawn
|
// 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");
|
DEBUG_LOG_FMT(PIXELENGINE, "VIDEO Set Finish");
|
||||||
|
|
||||||
|
@ -314,7 +321,7 @@ void SetFinish()
|
||||||
|
|
||||||
s_finish_interrupt_pending |= true;
|
s_finish_interrupt_pending |= true;
|
||||||
|
|
||||||
RaiseEvent();
|
RaiseEvent(cycles_into_future);
|
||||||
}
|
}
|
||||||
|
|
||||||
UPEAlphaReadReg GetAlphaReadMode()
|
UPEAlphaReadReg GetAlphaReadMode()
|
||||||
|
|
|
@ -61,8 +61,8 @@ void DoState(PointerWrap& p);
|
||||||
void RegisterMMIO(MMIO::Mapping* mmio, u32 base);
|
void RegisterMMIO(MMIO::Mapping* mmio, u32 base);
|
||||||
|
|
||||||
// gfx backend support
|
// gfx backend support
|
||||||
void SetToken(const u16 token, const bool interrupt);
|
void SetToken(const u16 token, const bool interrupt, int cycle_delay);
|
||||||
void SetFinish();
|
void SetFinish(int cycle_delay);
|
||||||
UPEAlphaReadReg GetAlphaReadMode();
|
UPEAlphaReadReg GetAlphaReadMode();
|
||||||
|
|
||||||
} // namespace PixelEngine
|
} // namespace PixelEngine
|
||||||
|
|
Loading…
Reference in New Issue