Use a waiting thread list in sceGe as well.

This commit is contained in:
Unknown W. Brackets 2013-09-08 11:49:24 -07:00
parent 5ec297c16c
commit 8ae6694e1d
4 changed files with 61 additions and 20 deletions

View file

@ -262,10 +262,12 @@ inline bool VerifyWait(SceUID threadID, WaitType waitType, SceUID uid) {
// Resume a thread from waiting for a particular object.
template <typename T>
inline void ResumeFromWait(SceUID threadID, WaitType waitType, SceUID uid, T result) {
inline bool ResumeFromWait(SceUID threadID, WaitType waitType, SceUID uid, T result) {
if (VerifyWait(threadID, waitType, uid)) {
__KernelResumeThreadFromWait(threadID, result);
return true;
}
return false;
}
};

View file

@ -15,22 +15,30 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "HLE.h"
#include "../MIPS/MIPS.h"
#include "../System.h"
#include "../CoreParameter.h"
#include "../CoreTiming.h"
#include "../Reporting.h"
#include "sceGe.h"
#include "sceKernelMemory.h"
#include "sceKernelThread.h"
#include "sceKernelInterrupt.h"
#include "../GPU/GPUState.h"
#include "../GPU/GPUInterface.h"
#include <map>
#include <vector>
#include "Core/HLE/HLE.h"
#include "Core/MIPS/MIPS.h"
#include "Core/System.h"
#include "Core/CoreParameter.h"
#include "Core/CoreTiming.h"
#include "Core/Reporting.h"
#include "Core/HLE/sceGe.h"
#include "Core/HLE/sceKernelMemory.h"
#include "Core/HLE/sceKernelThread.h"
#include "Core/HLE/sceKernelInterrupt.h"
#include "Core/HLE/KernelWaitHelpers.h"
#include "GPU/GPUState.h"
#include "GPU/GPUInterface.h"
static PspGeCallbackData ge_callback_data[16];
static bool ge_used_callbacks[16] = {0};
typedef std::vector<SceUID> WaitingThreadList;
static std::map<int, WaitingThreadList> listWaitingThreads;
static WaitingThreadList drawWaitingThreads;
struct GeInterruptData
{
int listid;
@ -162,7 +170,7 @@ void __GeExecuteSync(u64 userdata, int cyclesLate)
{
int listid = userdata >> 32;
WaitType waitType = (WaitType) (userdata & 0xFFFFFFFF);
bool wokeThreads = __KernelTriggerWait(waitType, listid, 0, "GeSync", true);
bool wokeThreads = __GeTriggerWait(waitType, listid);
gpu->SyncEnd(waitType, listid, wokeThreads);
}
@ -202,6 +210,9 @@ void __GeInit()
geInterruptEvent = CoreTiming::RegisterEvent("GeInterruptEvent", &__GeExecuteInterrupt);
geCycleEvent = CoreTiming::RegisterEvent("GeCycleEvent", &__GeCheckCycles);
listWaitingThreads.clear();
drawWaitingThreads.clear();
// When we're using separate CPU/GPU threads, we need to keep them in sync.
if (IsOnSeparateCPUThread()) {
CoreTiming::ScheduleEvent(usToCycles(geIntervalUs), geCycleEvent, 0);
@ -221,6 +232,9 @@ void __GeDoState(PointerWrap &p)
p.Do(geCycleEvent);
CoreTiming::RestoreRegisterEvent(geCycleEvent, "GeCycleEvent", &__GeCheckCycles);
p.Do(listWaitingThreads);
p.Do(drawWaitingThreads);
// Everything else is done in sceDisplay.
p.DoMarker("sceGe");
}
@ -255,12 +269,35 @@ bool __GeTriggerInterrupt(int listid, u32 pc, u64 atTicks)
void __GeWaitCurrentThread(WaitType type, SceUID waitId, const char *reason)
{
if (type == WAITTYPE_GEDRAWSYNC)
drawWaitingThreads.push_back(__KernelGetCurThread());
else if (type == WAITTYPE_GELISTSYNC)
listWaitingThreads[waitId].push_back(__KernelGetCurThread());
else
ERROR_LOG_REPORT(SCEGE, "__GeWaitCurrentThread: bad wait type");
__KernelWaitCurThread(type, waitId, 0, 0, false, reason);
}
void __GeTriggerWait(WaitType type, SceUID waitId, const char *reason, bool noSwitch)
bool __GeTriggerWait(WaitType type, SceUID waitId, WaitingThreadList &waitingThreads)
{
__KernelTriggerWait(type, waitId, 0, reason, noSwitch);
// TODO: Do they ever get a result other than 0?
bool wokeThreads = false;
for (auto it = waitingThreads.begin(), end = waitingThreads.end(); it != end; ++it)
wokeThreads |= HLEKernel::ResumeFromWait(*it, type, waitId, 0);
waitingThreads.clear();
return wokeThreads;
}
bool __GeTriggerWait(WaitType type, SceUID waitId)
{
if (type == WAITTYPE_GEDRAWSYNC)
return __GeTriggerWait(type, waitId, drawWaitingThreads);
else if (type == WAITTYPE_GELISTSYNC)
return __GeTriggerWait(type, waitId, listWaitingThreads[waitId]);
else
ERROR_LOG_REPORT(SCEGE, "__GeTriggerWait: bad wait type");
return false;
}
bool __GeHasPendingInterrupt()
@ -317,7 +354,9 @@ u32 sceGeListEnQueueHead(u32 listAddress, u32 stallAddress, int callbackId,
int sceGeListDeQueue(u32 listID)
{
WARN_LOG(SCEGE, "sceGeListDeQueue(%08x)", listID);
return gpu->DequeueList(listID);
int result = gpu->DequeueList(listID);
hleReSchedule("dlist dequeued");
return result;
}
int sceGeListUpdateStallAddr(u32 displayListID, u32 stallAddress)

View file

@ -44,7 +44,7 @@ void __GeShutdown();
bool __GeTriggerSync(WaitType waitType, int id, u64 atTicks);
bool __GeTriggerInterrupt(int listid, u32 pc, u64 atTicks);
void __GeWaitCurrentThread(WaitType type, SceUID waitId, const char *reason);
void __GeTriggerWait(WaitType type, SceUID waitId, const char *reason, bool noSwitch = false);
bool __GeTriggerWait(WaitType type, SceUID waitId);
bool __GeHasPendingInterrupt();

View file

@ -265,7 +265,7 @@ u32 GPUCommon::DequeueList(int listid) {
dlQueue.remove(listid);
dls[listid].waitTicks = 0;
__GeTriggerWait(WAITTYPE_GELISTSYNC, listid, "GeListSync");
__GeTriggerWait(WAITTYPE_GELISTSYNC, listid);
CheckDrawSync();
@ -893,7 +893,7 @@ void GPUCommon::InterruptEnd(int listid) {
// TODO: Unless the signal handler could change it?
if (dl.state == PSP_GE_DL_STATE_COMPLETED || dl.state == PSP_GE_DL_STATE_NONE) {
dl.waitTicks = 0;
__GeTriggerWait(WAITTYPE_GELISTSYNC, listid, "GeListSync", true);
__GeTriggerWait(WAITTYPE_GELISTSYNC, listid);
}
if (dl.signal == PSP_GE_SIGNAL_HANDLER_PAUSE)