Permalink
Browse files

Merge pull request #10056 from hrydgard/remove-multithreading-2

Remove the old style multithreading
  • Loading branch information...
hrydgard committed Nov 6, 2017
2 parents b280e30 + a827ad2 commit ea2fc552179f931790e8c344936ebfb543faec20
View
@@ -406,7 +406,6 @@ static bool DefaultSasThread() {
static ConfigSetting cpuSettings[] = {
ReportedConfigSetting("CPUCore", &g_Config.iCpuCore, &DefaultCpuCore, true, true),
ReportedConfigSetting("SeparateCPUThread", &g_Config.bSeparateCPUThread, false, true, true),
ReportedConfigSetting("SeparateSASThread", &g_Config.bSeparateSASThread, &DefaultSasThread, true, true),
ReportedConfigSetting("SeparateIOThread", &g_Config.bSeparateIOThread, true, true, true),
ReportedConfigSetting("IOTimingMethod", &g_Config.iIOTimingMethod, IOTIMING_FAST, true, true),
View
@@ -132,8 +132,6 @@ struct Config {
bool bFuncReplacements;
bool bHideSlowWarnings;
// Definitely cannot be changed while game is running.
bool bSeparateCPUThread;
bool bSeparateSASThread;
bool bSeparateIOThread;
int iIOTimingMethod;
View
@@ -57,10 +57,6 @@ static int geSyncEvent;
static int geInterruptEvent;
static int geCycleEvent;
// Let's try updating 10 times per vblank - this is the interval for geCycleEvent.
const int geIntervalUs = 1000000 / (60 * 10);
const int geBehindThresholdUs = 1000000 / (60 * 10);
class GeIntrHandler : public IntrHandler {
public:
GeIntrHandler() : IntrHandler(PSP_GE_INTR) {}
@@ -194,19 +190,7 @@ static void __GeExecuteInterrupt(u64 userdata, int cyclesLate) {
}
static void __GeCheckCycles(u64 userdata, int cyclesLate) {
u64 geTicks = gpu->GetTickEstimate();
if (geTicks != 0) {
if (CoreTiming::GetTicks() > geTicks + usToCycles(geBehindThresholdUs)) {
u64 diff = CoreTiming::GetTicks() - geTicks;
// Let the GPU thread catch up.
gpu->SyncThread();
CoreTiming::Advance();
}
}
// This may get out of step if we synced (because we don't correct for cyclesLate),
// but that's okay - __GeCheckCycles is a very rough way to synchronize anyway.
CoreTiming::ScheduleEvent(usToCycles(geIntervalUs), geCycleEvent, 0);
// Deprecated
}
void __GeInit() {
@@ -217,15 +201,12 @@ void __GeInit() {
geSyncEvent = CoreTiming::RegisterEvent("GeSyncEvent", &__GeExecuteSync);
geInterruptEvent = CoreTiming::RegisterEvent("GeInterruptEvent", &__GeExecuteInterrupt);
// Deprecated
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);
}
}
struct GeInterruptData_v1 {
@@ -270,20 +251,18 @@ void __GeDoState(PointerWrap &p) {
void __GeShutdown() {
}
// Warning: may be called from the GPU thread, if there is a separate one (multithread mode).
bool __GeTriggerSync(GPUSyncType type, int id, u64 atTicks) {
u64 userdata = (u64)id << 32 | (u64)type;
s64 future = atTicks - CoreTiming::GetTicks();
if (type == GPU_SYNC_DRAW) {
s64 left = CoreTiming::UnscheduleThreadsafeEvent(geSyncEvent, userdata);
s64 left = CoreTiming::UnscheduleEvent(geSyncEvent, userdata);
if (left > future)
future = left;
}
CoreTiming::ScheduleEvent_Threadsafe(future, geSyncEvent, userdata);
CoreTiming::ScheduleEvent(future, geSyncEvent, userdata);
return true;
}
// Warning: may be called from the GPU thread, if there is a separate one (multithread mode).
bool __GeTriggerInterrupt(int listid, u32 pc, u64 atTicks) {
GeInterruptData intrdata;
intrdata.listid = listid;
@@ -293,7 +272,7 @@ bool __GeTriggerInterrupt(int listid, u32 pc, u64 atTicks) {
ge_pending_cb.push_back(intrdata);
u64 userdata = (u64)listid << 32 | (u64) pc;
CoreTiming::ScheduleEvent_Threadsafe(atTicks - CoreTiming::GetTicks(), geInterruptEvent, userdata);
CoreTiming::ScheduleEvent(atTicks - CoreTiming::GetTicks(), geInterruptEvent, userdata);
return true;
}
@@ -504,7 +483,6 @@ static int sceGeUnsetCallback(u32 cbID) {
// unless some insane game pokes it and relies on it...
u32 sceGeSaveContext(u32 ctxAddr) {
DEBUG_LOG(SCEGE, "sceGeSaveContext(%08x)", ctxAddr);
gpu->SyncThread();
if (gpu->BusyDrawing()) {
WARN_LOG(SCEGE, "sceGeSaveContext(%08x): lists in process, aborting", ctxAddr);
@@ -524,7 +502,6 @@ u32 sceGeSaveContext(u32 ctxAddr) {
u32 sceGeRestoreContext(u32 ctxAddr) {
DEBUG_LOG(SCEGE, "sceGeRestoreContext(%08x)", ctxAddr);
gpu->SyncThread();
if (gpu->BusyDrawing()) {
WARN_LOG(SCEGE, "sceGeRestoreContext(%08x): lists in process, aborting", ctxAddr);
View
@@ -328,7 +328,6 @@ void CPU_RunLoop() {
switch (cpuThreadState) {
case CPU_THREAD_EXECUTE:
mipsr4k.RunLoopUntil(cpuThreadUntil);
gpu->FinishEventLoop();
CPU_NextState(CPU_THREAD_EXECUTE, CPU_THREAD_RUNNING);
break;
@@ -354,12 +353,6 @@ void CPU_RunLoop() {
coreState = CORE_POWERDOWN;
}
// Let's make sure the gpu has already cleaned up before we start freeing memory.
if (gpu) {
gpu->FinishEventLoop();
gpu->SyncThread(true);
}
CPU_Shutdown();
CPU_SetState(CPU_THREAD_NOT_RUNNING);
}
@@ -384,18 +377,15 @@ static void Core_UpdateDebugStats(bool flag) {
void System_Wake() {
// Ping the threads so they check coreState.
CPU_NextStateNot(CPU_THREAD_NOT_RUNNING, CPU_THREAD_SHUTDOWN);
if (gpu) {
gpu->FinishEventLoop();
}
}
// Ugly!
static bool pspIsInited = false;
static bool pspIsIniting = false;
static bool pspIsQuiting = false;
static bool pspIsQuitting = false;
bool PSP_InitStart(const CoreParameter &coreParam, std::string *error_string) {
if (pspIsIniting || pspIsQuiting) {
if (pspIsIniting || pspIsQuitting) {
return false;
}
@@ -415,7 +405,9 @@ bool PSP_InitStart(const CoreParameter &coreParam, std::string *error_string) {
coreParameter.errorString = "";
pspIsIniting = true;
if (g_Config.bSeparateCPUThread) {
// Keeping this around because we might need it in the future.
const bool separateCPUThread = false;
if (separateCPUThread) {
Core_ListenShutdown(System_Wake);
CPU_SetState(CPU_THREAD_PENDING);
cpuThread = new std::thread(&CPU_RunLoop);
@@ -438,7 +430,7 @@ bool PSP_InitUpdate(std::string *error_string) {
return true;
}
if (g_Config.bSeparateCPUThread && !CPU_IsReady()) {
if (!CPU_IsReady()) {
return false;
}
@@ -459,7 +451,8 @@ bool PSP_InitUpdate(std::string *error_string) {
bool PSP_Init(const CoreParameter &coreParam, std::string *error_string) {
PSP_InitStart(coreParam, error_string);
if (g_Config.bSeparateCPUThread) {
// For a potential resurrection of separate CPU thread later.
if (false) {
CPU_WaitStatus(cpuThreadReplyCond, &CPU_IsReady);
}
@@ -472,12 +465,12 @@ bool PSP_IsIniting() {
}
bool PSP_IsInited() {
return pspIsInited && !pspIsQuiting;
return pspIsInited && !pspIsQuitting;
}
void PSP_Shutdown() {
// Do nothing if we never inited.
if (!pspIsInited && !pspIsIniting && !pspIsQuiting) {
if (!pspIsInited && !pspIsIniting && !pspIsQuitting) {
return;
}
@@ -488,7 +481,7 @@ void PSP_Shutdown() {
#endif
// Make sure things know right away that PSP memory, etc. is going away.
pspIsQuiting = true;
pspIsQuitting = true;
if (coreState == CORE_RUNNING)
Core_UpdateState(CORE_ERROR);
Core_NotifyShutdown();
@@ -507,7 +500,7 @@ void PSP_Shutdown() {
currentMIPS = 0;
pspIsInited = false;
pspIsIniting = false;
pspIsQuiting = false;
pspIsQuitting = false;
g_Config.unloadGameConfig();
}
@@ -532,40 +525,34 @@ void PSP_RunLoopUntil(u64 globalticks) {
return;
}
// Switch the CPU thread on or off, as the case may be.
bool useCPUThread = g_Config.bSeparateCPUThread;
// We no longer allow a separate CPU thread but if we add a render queue
// to GL we're gonna need it.
bool useCPUThread = false;
if (useCPUThread && cpuThread == nullptr) {
// Need to start the cpu thread.
Core_ListenShutdown(System_Wake);
CPU_SetState(CPU_THREAD_RESUME);
cpuThread = new std::thread(&CPU_RunLoop);
cpuThreadID = cpuThread->get_id();
cpuThread->detach();
if (gpu) {
gpu->SetThreadEnabled(true);
}
// Probably needs to tell the gpu that it will need to queue up its output
// on another thread.
CPU_WaitStatus(cpuThreadReplyCond, &CPU_IsReady);
} else if (!useCPUThread && cpuThread != nullptr) {
CPU_SetState(CPU_THREAD_QUIT);
CPU_WaitStatus(cpuThreadReplyCond, &CPU_IsShutdown);
delete cpuThread;
cpuThread = nullptr;
cpuThreadID = std::thread::id();
if (gpu) {
gpu->SetThreadEnabled(false);
}
}
if (cpuThread != nullptr) {
// Tell the gpu a new frame is about to begin, before we start the CPU.
gpu->SyncBeginFrame();
cpuThreadUntil = globalticks;
if (CPU_NextState(CPU_THREAD_RUNNING, CPU_THREAD_EXECUTE)) {
// The CPU doesn't actually respect cpuThreadUntil well, especially when skipping frames.
// TODO: Something smarter? Or force CPU to bail periodically?
while (!CPU_IsReady()) {
gpu->RunEventsUntil(CoreTiming::GetTicks() + msToCycles(1000));
// Have the GPU do stuff here.
if (coreState != CORE_RUNNING) {
CPU_WaitStatus(cpuThreadReplyCond, &CPU_IsReady);
}
@@ -400,6 +400,7 @@ void SoftwareTransform(
// rectangle out of many. Quite a small optimization though.
// Experiment: Disable on PowerVR (see issue #6290)
// TODO: This bleeds outside the play area in non-buffered mode. Big deal? Probably not.
// TODO: Allow creating a depth clear and a color draw.
bool reallyAClear = false;
if (maxIndex > 1 && prim == GE_PRIM_RECTANGLES && gstate.isModeClear()) {
int scissorX2 = gstate.getScissorX2() + 1;
@@ -17,6 +17,7 @@
#pragma once
#include <map>
#include <d3d11.h>
#include <d3d11_1.h>
@@ -190,7 +191,8 @@ class DrawEngineD3D11 : public DrawEngineCommon {
PushBufferD3D11 *pushVerts_;
PushBufferD3D11 *pushInds_;
// D3D11 state object caches
// D3D11 state object caches.
// TODO: Change them to DenseHashMaps.
std::map<uint64_t, ID3D11BlendState *> blendCache_;
std::map<uint64_t, ID3D11BlendState1 *> blendCache1_;
std::map<uint64_t, ID3D11DepthStencilState *> depthStencilCache_;
View
@@ -286,7 +286,7 @@ void GPU_D3D11::DeviceRestore() {
// Nothing needed.
}
void GPU_D3D11::InitClearInternal() {
void GPU_D3D11::InitClear() {
bool useNonBufferedRendering = g_Config.iRenderingMode == FB_NON_BUFFERED_MODE;
if (useNonBufferedRendering) {
// device_->Clear(0, NULL, D3DCLEAR_STENCIL | D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.f, 0);
@@ -305,8 +305,8 @@ void GPU_D3D11::BeginHostFrame() {
}
}
void GPU_D3D11::ReapplyGfxStateInternal() {
GPUCommon::ReapplyGfxStateInternal();
void GPU_D3D11::ReapplyGfxState() {
GPUCommon::ReapplyGfxState();
// TODO: Dirty our caches for depth states etc
}
@@ -316,8 +316,8 @@ void GPU_D3D11::EndHostFrame() {
draw_->BindPipeline(nullptr);
}
void GPU_D3D11::BeginFrameInternal() {
GPUCommon::BeginFrameInternal();
void GPU_D3D11::BeginFrame() {
GPUCommon::BeginFrame();
textureCacheD3D11_->StartFrame();
drawEngine_.BeginFrame();
@@ -338,13 +338,6 @@ void GPU_D3D11::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat f
}
bool GPU_D3D11::FramebufferDirty() {
// FIXME: Workaround for displaylists sometimes hanging unprocessed. Not yet sure of the cause.
if (ThreadEnabled()) {
// FIXME: Workaround for displaylists sometimes hanging unprocessed. Not yet sure of the cause.
ScheduleEvent(GPU_EVENT_PROCESS_QUEUE);
// Allow it to process fully before deciding if it's dirty.
SyncThread();
}
VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB();
if (vfb) {
bool dirty = vfb->dirtyAfterDisplay;
@@ -353,15 +346,8 @@ bool GPU_D3D11::FramebufferDirty() {
}
return true;
}
bool GPU_D3D11::FramebufferReallyDirty() {
// FIXME: Workaround for displaylists sometimes hanging unprocessed. Not yet sure of the cause.
if (ThreadEnabled()) {
// FIXME: Workaround for displaylists sometimes hanging unprocessed. Not yet sure of the cause.
ScheduleEvent(GPU_EVENT_PROCESS_QUEUE);
// Allow it to process fully before deciding if it's dirty.
SyncThread();
}
bool GPU_D3D11::FramebufferReallyDirty() {
VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB();
if (vfb) {
bool dirty = vfb->reallyDirtyAfterDisplay;
@@ -371,7 +357,7 @@ bool GPU_D3D11::FramebufferReallyDirty() {
return true;
}
void GPU_D3D11::CopyDisplayToOutputInternal() {
void GPU_D3D11::CopyDisplayToOutput() {
float blendColor[4]{};
context_->OMSetBlendState(stockD3D11.blendStateDisabledWithColorMask[0xF], blendColor, 0xFFFFFFFF);
View
@@ -40,7 +40,7 @@ class GPU_D3D11 : public GPUCommon {
void PreExecuteOp(u32 op, u32 diff) override;
void ExecuteOp(u32 op, u32 diff) override;
void ReapplyGfxStateInternal() override;
void ReapplyGfxState() override;
void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override;
void GetStats(char *buffer, size_t bufsize) override;
void ClearCacheNextFrame() override;
@@ -96,9 +96,9 @@ class GPU_D3D11 : public GPUCommon {
void CheckFlushOp(int cmd, u32 diff);
void BuildReportingInfo();
void InitClearInternal() override;
void BeginFrameInternal() override;
void CopyDisplayToOutputInternal() override;
void InitClear() override;
void BeginFrame() override;
void CopyDisplayToOutput() override;
ID3D11Device *device_;
ID3D11DeviceContext *context_;
Oops, something went wrong.

1 comment on commit ea2fc55

@zminhquanz

This comment has been minimized.

Show comment
Hide comment
@zminhquanz

zminhquanz Nov 7, 2017

Contributor

i'm waiting for OpenGL / OpenGL ES to support multithreading on old devices

Contributor

zminhquanz commented on ea2fc55 Nov 7, 2017

i'm waiting for OpenGL / OpenGL ES to support multithreading on old devices

Please sign in to comment.