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

Remove the old style multithreading
This commit is contained in:
Henrik Rydgård authored and GitHub committed 2017-11-06 20:37:06 +01:00
commit ea2fc55217
22 files changed
+98 -564

No files matched your search

-1
View File
@@ -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),
-2
View File
@@ -132,8 +132,6 @@ public:
bool bFuncReplacements;
bool bHideSlowWarnings;
// Definitely cannot be changed while game is running.
bool bSeparateCPUThread;
bool bSeparateSASThread;
bool bSeparateIOThread;
int iIOTimingMethod;
+6 -29
View File
@@ -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);
+18 -31
View File
@@ -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,8 +525,9 @@ 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);
@@ -541,9 +535,8 @@ void PSP_RunLoopUntil(u64 globalticks) {
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);
@@ -551,21 +544,15 @@ void PSP_RunLoopUntil(u64 globalticks) {
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);
}
+1
View File
@@ -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;
+3 -1
View File
@@ -17,6 +17,7 @@
#pragma once
#include <map>
#include <d3d11.h>
#include <d3d11_1.h>
@@ -190,7 +191,8 @@ private:
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_;
+7 -21
View File
@@ -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);
+4 -4
View File
@@ -40,7 +40,7 @@ public:
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 @@ private:
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_;
+7 -21
View File
@@ -251,7 +251,7 @@ void GPU_DX9::DeviceRestore() {
// Nothing needed.
}
void GPU_DX9::InitClearInternal() {
void GPU_DX9::InitClear() {
bool useNonBufferedRendering = g_Config.iRenderingMode == FB_NON_BUFFERED_MODE;
if (useNonBufferedRendering) {
dxstate.depthWrite.set(true);
@@ -272,12 +272,12 @@ void GPU_DX9::BeginHostFrame() {
}
}
void GPU_DX9::ReapplyGfxStateInternal() {
void GPU_DX9::ReapplyGfxState() {
dxstate.Restore();
GPUCommon::ReapplyGfxStateInternal();
GPUCommon::ReapplyGfxState();
}
void GPU_DX9::BeginFrameInternal() {
void GPU_DX9::BeginFrame() {
// Turn off vsync when unthrottled
int desiredVSyncInterval = g_Config.bVSync ? 1 : 0;
if ((PSP_CoreParameter().unthrottle) || (PSP_CoreParameter().fpsLimit == 1))
@@ -292,7 +292,7 @@ void GPU_DX9::BeginFrameInternal() {
depalShaderCache_.Decimate();
// fragmentTestCache_.Decimate();
GPUCommon::BeginFrameInternal();
GPUCommon::BeginFrame();
shaderManagerDX9_->DirtyShader();
framebufferManager_->BeginFrame();
@@ -304,13 +304,6 @@ void GPU_DX9::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat for
}
bool GPU_DX9::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;
@@ -319,15 +312,8 @@ bool GPU_DX9::FramebufferDirty() {
}
return true;
}
bool GPU_DX9::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_DX9::FramebufferReallyDirty() {
VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB();
if (vfb) {
bool dirty = vfb->reallyDirtyAfterDisplay;
@@ -337,7 +323,7 @@ bool GPU_DX9::FramebufferReallyDirty() {
return true;
}
void GPU_DX9::CopyDisplayToOutputInternal() {
void GPU_DX9::CopyDisplayToOutput() {
dxstate.depthWrite.set(true);
dxstate.colorMask.set(true, true, true, true);
+4 -4
View File
@@ -41,7 +41,7 @@ public:
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 @@ private:
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;
LPDIRECT3DDEVICE9 device_;
LPDIRECT3DDEVICE9EX deviceEx_;
+8 -17
View File
@@ -401,13 +401,14 @@ void GPU_GLES::DeviceRestore() {
UpdateVsyncInterval(true);
}
void GPU_GLES::ReinitializeInternal() {
void GPU_GLES::Reinitialize() {
GPUCommon::Reinitialize();
textureCacheGL_->Clear(true);
depalShaderCache_.Clear();
framebufferManagerGL_->DestroyAllFBOs();
}
void GPU_GLES::InitClearInternal() {
void GPU_GLES::InitClear() {
bool useNonBufferedRendering = g_Config.iRenderingMode == FB_NON_BUFFERED_MODE;
if (useNonBufferedRendering) {
glstate.depthWrite.set(GL_TRUE);
@@ -467,13 +468,13 @@ void GPU_GLES::UpdateCmdInfo() {
}
}
void GPU_GLES::ReapplyGfxStateInternal() {
void GPU_GLES::ReapplyGfxState() {
drawEngine_.RestoreVAO();
glstate.Restore();
GPUCommon::ReapplyGfxStateInternal();
GPUCommon::ReapplyGfxState();
}
void GPU_GLES::BeginFrameInternal() {
void GPU_GLES::BeginFrame() {
UpdateVsyncInterval(resized_);
resized_ = false;
@@ -483,7 +484,7 @@ void GPU_GLES::BeginFrameInternal() {
depalShaderCache_.Decimate();
fragmentTestCache_.Decimate();
GPUCommon::BeginFrameInternal();
GPUCommon::BeginFrame();
// Save the cache from time to time. TODO: How often?
if (!shaderCachePath_.empty() && (gpuStats.numFlips & 1023) == 0) {
@@ -504,11 +505,6 @@ void GPU_GLES::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat fo
}
bool GPU_GLES::FramebufferDirty() {
if (ThreadEnabled()) {
// Allow it to process fully before deciding if it's dirty.
SyncThread();
}
VirtualFramebuffer *vfb = framebufferManagerGL_->GetDisplayVFB();
if (vfb) {
bool dirty = vfb->dirtyAfterDisplay;
@@ -519,11 +515,6 @@ bool GPU_GLES::FramebufferDirty() {
}
bool GPU_GLES::FramebufferReallyDirty() {
if (ThreadEnabled()) {
// Allow it to process fully before deciding if it's dirty.
SyncThread();
}
VirtualFramebuffer *vfb = framebufferManagerGL_->GetDisplayVFB();
if (vfb) {
bool dirty = vfb->reallyDirtyAfterDisplay;
@@ -533,7 +524,7 @@ bool GPU_GLES::FramebufferReallyDirty() {
return true;
}
void GPU_GLES::CopyDisplayToOutputInternal() {
void GPU_GLES::CopyDisplayToOutput() {
// Flush anything left over.
framebufferManagerGL_->RebindFramebuffer();
drawEngine_.Flush();
+5 -5
View File
@@ -41,7 +41,7 @@ public:
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;
@@ -95,10 +95,10 @@ private:
void CheckFlushOp(int cmd, u32 diff);
void BuildReportingInfo();
void InitClearInternal() override;
void BeginFrameInternal() override;
void CopyDisplayToOutputInternal() override;
void ReinitializeInternal() override;
void InitClear() override;
void BeginFrame() override;
void CopyDisplayToOutput() override;
void Reinitialize() override;
inline void UpdateVsyncInterval(bool force);
void UpdateCmdInfo();
+16 -199
View File
@@ -359,11 +359,9 @@ GPUCommon::GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw) :
// The compiler was not rounding the struct size up to an 8 byte boundary, which
// you'd expect due to the int64 field, but the Linux ABI apparently does not require that.
static_assert(sizeof(DisplayList) == 456, "Bad DisplayList size");
listLock.set_enabled(g_Config.bSeparateCPUThread);
Reinitialize();
SetupColorConv();
SetThreadEnabled(g_Config.bSeparateCPUThread);
gstate.Reset();
gstate_c.Reset();
gpuStats.Reset();
@@ -383,16 +381,7 @@ void GPUCommon::EndHostFrame() {
}
void GPUCommon::InitClear() {
ScheduleEvent(GPU_EVENT_INIT_CLEAR);
}
void GPUCommon::CopyDisplayToOutput() {
ScheduleEvent(GPU_EVENT_COPY_DISPLAY_TO_OUTPUT);
}
void GPUCommon::Reinitialize() {
easy_guard guard(listLock);
memset(dls, 0, sizeof(dls));
for (int i = 0; i < DisplayListMaxCount; ++i) {
dls[i].state = PSP_GE_DL_STATE_NONE;
@@ -400,14 +389,12 @@ void GPUCommon::Reinitialize() {
}
nextListID = 0;
currentList = NULL;
currentList = nullptr;
isbreak = false;
drawCompleteTicks = 0;
busyTicks = 0;
timeSpentStepping_ = 0.0;
interruptsEnabled_ = true;
UpdateTickEstimate(0);
ScheduleEvent(GPU_EVENT_REINITIALIZE);
}
int GPUCommon::EstimatePerVertexCost() {
@@ -440,7 +427,6 @@ int GPUCommon::EstimatePerVertexCost() {
}
void GPUCommon::PopDLQueue() {
easy_guard guard(listLock);
if(!dlQueue.empty()) {
dlQueue.pop_front();
if(!dlQueue.empty()) {
@@ -449,7 +435,7 @@ void GPUCommon::PopDLQueue() {
if (running)
currentList->state = PSP_GE_DL_STATE_RUNNING;
} else {
currentList = NULL;
currentList = nullptr;
}
}
}
@@ -457,7 +443,6 @@ void GPUCommon::PopDLQueue() {
bool GPUCommon::BusyDrawing() {
u32 state = DrawSync(1);
if (state == PSP_GE_LIST_DRAWING || state == PSP_GE_LIST_STALLING) {
easy_guard guard(listLock);
if (currentList && currentList->state != PSP_GE_DL_STATE_PAUSED) {
return true;
}
@@ -474,12 +459,6 @@ void GPUCommon::DumpNextFrame() {
}
u32 GPUCommon::DrawSync(int mode) {
if (ThreadEnabled()) {
// Sync first, because the CPU is usually faster than the emulated GPU.
SyncThread();
}
easy_guard guard(listLock);
if (mode < 0 || mode > 1)
return SCE_KERNEL_ERROR_INVALID_MODE;
@@ -521,7 +500,6 @@ u32 GPUCommon::DrawSync(int mode) {
}
void GPUCommon::CheckDrawSync() {
easy_guard guard(listLock);
if (dlQueue.empty()) {
for (int i = 0; i < DisplayListMaxCount; ++i)
dls[i].state = PSP_GE_DL_STATE_NONE;
@@ -529,12 +507,6 @@ void GPUCommon::CheckDrawSync() {
}
int GPUCommon::ListSync(int listid, int mode) {
if (ThreadEnabled()) {
// Sync first, because the CPU is usually faster than the emulated GPU.
SyncThread();
}
easy_guard guard(listLock);
if (listid < 0 || listid >= DisplayListMaxCount)
return SCE_KERNEL_ERROR_INVALID_ID;
@@ -579,8 +551,7 @@ int GPUCommon::ListSync(int listid, int mode) {
}
int GPUCommon::GetStack(int index, u32 stackPtr) {
easy_guard guard(listLock);
if (currentList == NULL) {
if (!currentList) {
// Seems like it doesn't return an error code?
return 0;
}
@@ -605,7 +576,6 @@ int GPUCommon::GetStack(int index, u32 stackPtr) {
}
u32 GPUCommon::EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer<PspGeListArgs> args, bool head) {
easy_guard guard(listLock);
// TODO Check the stack values in missing arg and ajust the stack depth
// Check alignment
@@ -704,7 +674,6 @@ u32 GPUCommon::EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer<Ps
drawCompleteTicks = (u64)-1;
// TODO save context when starting the list if param is set
guard.unlock();
ProcessDLQueue();
}
@@ -712,7 +681,6 @@ u32 GPUCommon::EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer<Ps
}
u32 GPUCommon::DequeueList(int listid) {
easy_guard guard(listLock);
if (listid < 0 || listid >= DisplayListMaxCount || dls[listid].state == PSP_GE_DL_STATE_NONE)
return SCE_KERNEL_ERROR_INVALID_ID;
@@ -736,7 +704,6 @@ u32 GPUCommon::DequeueList(int listid) {
}
u32 GPUCommon::UpdateStall(int listid, u32 newstall) {
easy_guard guard(listLock);
if (listid < 0 || listid >= DisplayListMaxCount || dls[listid].state == PSP_GE_DL_STATE_NONE)
return SCE_KERNEL_ERROR_INVALID_ID;
auto &dl = dls[listid];
@@ -745,14 +712,12 @@ u32 GPUCommon::UpdateStall(int listid, u32 newstall) {
dl.stall = newstall & 0x0FFFFFFF;
guard.unlock();
ProcessDLQueue();
return 0;
}
u32 GPUCommon::Continue() {
easy_guard guard(listLock);
if (!currentList)
return 0;
@@ -788,13 +753,11 @@ u32 GPUCommon::Continue() {
return -1;
}
guard.unlock();
ProcessDLQueue();
return 0;
}
u32 GPUCommon::Break(int mode) {
easy_guard guard(listLock);
if (mode < 0 || mode > 1)
return SCE_KERNEL_ERROR_INVALID_MODE;
@@ -883,8 +846,6 @@ bool GPUCommon::InterpretList(DisplayList &list) {
start = time_now_d();
}
easy_guard guard(listLock);
if (list.state == PSP_GE_DL_STATE_PAUSED)
return false;
currentList = &list;
@@ -908,14 +869,12 @@ bool GPUCommon::InterpretList(DisplayList &list) {
list.interrupted = false;
gpuState = list.pc == list.stall ? GPUSTATE_STALL : GPUSTATE_RUNNING;
guard.unlock();
debugRecording_ = GPURecord::IsActive();
const bool useDebugger = host->GPUDebuggingActive() || debugRecording_;
const bool useFastRunLoop = !dumpThisFrame_ && !useDebugger;
while (gpuState == GPUSTATE_RUNNING) {
{
easy_guard innerGuard(listLock);
if (list.pc == list.stall) {
gpuState = GPUSTATE_STALL;
downcount = 0;
@@ -929,7 +888,6 @@ bool GPUCommon::InterpretList(DisplayList &list) {
}
{
easy_guard innerGuard(listLock);
downcount = list.stall == 0 ? 0x0FFFFFFF : (list.stall - list.pc) / 4;
if (gpuState == GPUSTATE_STALL && list.stall != list.pc) {
@@ -959,10 +917,6 @@ bool GPUCommon::InterpretList(DisplayList &list) {
}
void GPUCommon::BeginFrame() {
ScheduleEvent(GPU_EVENT_BEGIN_FRAME);
}
void GPUCommon::BeginFrameInternal() {
if (dumpNextFrame_) {
NOTICE_LOG(G3D, "DUMPING THIS FRAME");
dumpThisFrame_ = true;
@@ -1026,14 +980,6 @@ void GPUCommon::UpdatePC(u32 currentPC, u32 newPC) {
}
void GPUCommon::ReapplyGfxState() {
if (IsOnSeparateCPUThread()) {
ScheduleEvent(GPU_EVENT_REAPPLY_GFX_STATE);
} else {
ReapplyGfxStateInternal();
}
}
void GPUCommon::ReapplyGfxStateInternal() {
// The commands are embedded in the command memory so we can just reexecute the words. Convenient.
// To be safe we pass 0xFFFFFFFF as the diff.
@@ -1064,55 +1010,7 @@ inline void GPUCommon::UpdateState(GPURunState state) {
downcount = 0;
}
void GPUCommon::ProcessEvent(GPUEvent ev) {
switch (ev.type) {
case GPU_EVENT_PROCESS_QUEUE:
ProcessDLQueueInternal();
break;
case GPU_EVENT_REAPPLY_GFX_STATE:
ReapplyGfxStateInternal();
break;
case GPU_EVENT_INIT_CLEAR:
InitClearInternal();
break;
case GPU_EVENT_BEGIN_FRAME:
BeginFrameInternal();
break;
case GPU_EVENT_COPY_DISPLAY_TO_OUTPUT:
CopyDisplayToOutputInternal();
break;
case GPU_EVENT_INVALIDATE_CACHE:
InvalidateCacheInternal(ev.invalidate_cache.addr, ev.invalidate_cache.size, ev.invalidate_cache.type);
break;
case GPU_EVENT_FB_MEMCPY:
PerformMemoryCopyInternal(ev.fb_memcpy.dst, ev.fb_memcpy.src, ev.fb_memcpy.size);
break;
case GPU_EVENT_FB_MEMSET:
PerformMemorySetInternal(ev.fb_memset.dst, ev.fb_memset.v, ev.fb_memset.size);
break;
case GPU_EVENT_FB_STENCIL_UPLOAD:
PerformStencilUploadInternal(ev.fb_stencil_upload.dst, ev.fb_stencil_upload.size);
break;
case GPU_EVENT_REINITIALIZE:
break;
default:
ERROR_LOG_REPORT(G3D, "Unexpected GPU event type: %d", (int)ev);
break;
}
}
int GPUCommon::GetNextListIndex() {
easy_guard guard(listLock);
auto iter = dlQueue.begin();
if (iter != dlQueue.end()) {
return *iter;
@@ -1121,15 +1019,9 @@ int GPUCommon::GetNextListIndex() {
}
}
bool GPUCommon::ProcessDLQueue() {
ScheduleEvent(GPU_EVENT_PROCESS_QUEUE);
return true;
}
void GPUCommon::ProcessDLQueueInternal() {
void GPUCommon::ProcessDLQueue() {
startingTicks = CoreTiming::GetTicks();
cyclesExecuted = 0;
UpdateTickEstimate(std::max(busyTicks, startingTicks + cyclesExecuted));
// Seems to be correct behaviour to process the list anyway?
if (startingTicks < busyTicks) {
@@ -1143,25 +1035,20 @@ void GPUCommon::ProcessDLQueueInternal() {
if (!InterpretList(l)) {
return;
} else {
easy_guard guard(listLock);
// Some other list could've taken the spot while we dilly-dallied around.
if (l.state != PSP_GE_DL_STATE_QUEUED) {
// At the end, we can remove it from the queue and continue.
dlQueue.erase(std::remove(dlQueue.begin(), dlQueue.end(), listIndex), dlQueue.end());
}
UpdateTickEstimate(std::max(busyTicks, startingTicks + cyclesExecuted));
}
}
easy_guard guard(listLock);
currentList = NULL;
currentList = nullptr;
drawCompleteTicks = startingTicks + cyclesExecuted;
busyTicks = std::max(busyTicks, drawCompleteTicks);
__GeTriggerSync(GPU_SYNC_DRAW, 1, drawCompleteTicks);
// Since the event is in CoreTiming, we're in sync. Just set 0 now.
UpdateTickEstimate(0);
}
void GPUCommon::PreExecuteOp(u32 op, u32 diff) {
@@ -1181,12 +1068,10 @@ void GPUCommon::Execute_Iaddr(u32 op, u32 diff) {
}
void GPUCommon::Execute_Origin(u32 op, u32 diff) {
easy_guard guard(listLock);
gstate_c.offsetAddr = currentList->pc;
}
void GPUCommon::Execute_Jump(u32 op, u32 diff) {
easy_guard guard(listLock);
const u32 target = gstate_c.getRelativeAddress(op & 0x00FFFFFC);
#ifdef _DEBUG
if (!Memory::IsValidAddress(target)) {
@@ -1201,7 +1086,6 @@ void GPUCommon::Execute_Jump(u32 op, u32 diff) {
void GPUCommon::Execute_BJump(u32 op, u32 diff) {
if (!currentList->bboxResult) {
// bounding box jump.
easy_guard guard(listLock);
const u32 target = gstate_c.getRelativeAddress(op & 0x00FFFFFC);
if (Memory::IsValidAddress(target)) {
UpdatePC(currentList->pc, target - 4);
@@ -1214,7 +1098,6 @@ void GPUCommon::Execute_BJump(u32 op, u32 diff) {
void GPUCommon::Execute_Call(u32 op, u32 diff) {
PROFILE_THIS_SCOPE("gpu_call");
easy_guard guard(listLock);
// Saint Seiya needs correct support for relative calls.
const u32 retval = currentList->pc + 4;
@@ -1253,7 +1136,6 @@ void GPUCommon::Execute_Call(u32 op, u32 diff) {
}
void GPUCommon::Execute_Ret(u32 op, u32 diff) {
easy_guard guard(listLock);
if (currentList->stackptr == 0) {
DEBUG_LOG_REPORT(G3D, "RET: Stack empty!");
} else {
@@ -1275,7 +1157,6 @@ void GPUCommon::Execute_Ret(u32 op, u32 diff) {
void GPUCommon::Execute_End(u32 op, u32 diff) {
Flush();
easy_guard guard(listLock);
const u32 prev = Memory::ReadUnchecked_U32(currentList->pc - 4);
UpdatePC(currentList->pc, currentList->pc);
// Count in a few extra cycles on END.
@@ -1419,7 +1300,7 @@ void GPUCommon::Execute_End(u32 op, u32 diff) {
__GeTriggerSync(GPU_SYNC_LIST, currentList->id, currentList->waitTicks);
if (currentList->started && currentList->context.IsValid()) {
gstate.Restore(currentList->context);
ReapplyGfxStateInternal();
ReapplyGfxState();
}
}
break;
@@ -1600,7 +1481,6 @@ void GPUCommon::Execute_WorldMtxNum(u32 op, u32 diff) {
gstate.worldmtxnum = (GE_CMD_WORLDMATRIXNUMBER << 24) | ((op + count) & 0xF);
// Skip over the loaded data, it's done now.
easy_guard innerGuard(listLock);
UpdatePC(currentList->pc, currentList->pc + count * 4);
currentList->pc += count * 4;
}
@@ -1648,7 +1528,6 @@ void GPUCommon::Execute_ViewMtxNum(u32 op, u32 diff) {
gstate.viewmtxnum = (GE_CMD_VIEWMATRIXNUMBER << 24) | ((op + count) & 0xF);
// Skip over the loaded data, it's done now.
easy_guard innerGuard(listLock);
UpdatePC(currentList->pc, currentList->pc + count * 4);
currentList->pc += count * 4;
}
@@ -1696,7 +1575,6 @@ void GPUCommon::Execute_ProjMtxNum(u32 op, u32 diff) {
gstate.projmtxnum = (GE_CMD_PROJMATRIXNUMBER << 24) | ((op + count) & 0x1F);
// Skip over the loaded data, it's done now.
easy_guard innerGuard(listLock);
UpdatePC(currentList->pc, currentList->pc + count * 4);
currentList->pc += count * 4;
}
@@ -1745,7 +1623,6 @@ void GPUCommon::Execute_TgenMtxNum(u32 op, u32 diff) {
gstate.texmtxnum = (GE_CMD_TGENMATRIXNUMBER << 24) | ((op + count) & 0xF);
// Skip over the loaded data, it's done now.
easy_guard innerGuard(listLock);
UpdatePC(currentList->pc, currentList->pc + count * 4);
currentList->pc += count * 4;
}
@@ -1812,7 +1689,6 @@ void GPUCommon::Execute_BoneMtxNum(u32 op, u32 diff) {
gstate.boneMatrixNumber = (GE_CMD_BONEMATRIXNUMBER << 24) | ((op + count) & 0x7F);
// Skip over the loaded data, it's done now.
easy_guard innerGuard(listLock);
UpdatePC(currentList->pc, currentList->pc + count * 4);
currentList->pc += count * 4;
}
@@ -2028,8 +1904,6 @@ struct DisplayList_v2 {
};
void GPUCommon::DoState(PointerWrap &p) {
easy_guard guard(listLock);
auto s = p.Section("GPUCommon", 1, 4);
if (!s)
return;
@@ -2108,7 +1982,6 @@ void GPUCommon::InterruptStart(int listid) {
interruptRunning = true;
}
void GPUCommon::InterruptEnd(int listid) {
easy_guard guard(listLock);
interruptRunning = false;
isbreak = false;
@@ -2124,13 +1997,11 @@ void GPUCommon::InterruptEnd(int listid) {
__GeTriggerWait(GPU_SYNC_LIST, listid);
}
guard.unlock();
ProcessDLQueue();
}
// TODO: Maybe cleaner to keep this in GE and trigger the clear directly?
void GPUCommon::SyncEnd(GPUSyncType waitType, int listid, bool wokeThreads) {
easy_guard guard(listLock);
if (waitType == GPU_SYNC_DRAW && wokeThreads)
{
for (int i = 0; i < DisplayListMaxCount; ++i) {
@@ -2142,7 +2013,6 @@ void GPUCommon::SyncEnd(GPUSyncType waitType, int listid, bool wokeThreads) {
}
bool GPUCommon::GetCurrentDisplayList(DisplayList &list) {
easy_guard guard(listLock);
if (!currentList) {
return false;
}
@@ -2153,7 +2023,6 @@ bool GPUCommon::GetCurrentDisplayList(DisplayList &list) {
std::vector<DisplayList> GPUCommon::ActiveDisplayLists() {
std::vector<DisplayList> result;
easy_guard guard(listLock);
for (auto it = dlQueue.begin(), end = dlQueue.end(); it != end; ++it) {
result.push_back(dls[*it]);
}
@@ -2167,7 +2036,6 @@ void GPUCommon::ResetListPC(int listID, u32 pc) {
return;
}
easy_guard guard(listLock);
dls[listID].pc = pc;
}
@@ -2177,7 +2045,6 @@ void GPUCommon::ResetListStall(int listID, u32 stall) {
return;
}
easy_guard guard(listLock);
dls[listID].stall = stall;
}
@@ -2187,7 +2054,6 @@ void GPUCommon::ResetListState(int listID, DisplayListState state) {
return;
}
easy_guard guard(listLock);
dls[listID].state = state;
}
@@ -2339,38 +2205,17 @@ void GPUCommon::DoBlockTransfer(u32 skipDrawReason) {
cyclesExecuted += ((height * width * bpp) * 16) / 10;
}
void GPUCommon::PerformMemoryCopyInternal(u32 dest, u32 src, int size) {
if (!framebufferManager_->NotifyFramebufferCopy(src, dest, size, false, gstate_c.skipDrawReason)) {
// We use a little hack for Download/Upload using a VRAM mirror.
// Since they're identical we don't need to copy.
if (!Memory::IsVRAMAddress(dest) || (dest ^ 0x00400000) != src) {
Memory::Memcpy(dest, src, size);
}
}
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
}
void GPUCommon::PerformMemorySetInternal(u32 dest, u8 v, int size) {
if (!framebufferManager_->NotifyFramebufferCopy(dest, dest, size, true, gstate_c.skipDrawReason)) {
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
}
}
bool GPUCommon::PerformMemoryCopy(u32 dest, u32 src, int size) {
// Track stray copies of a framebuffer in RAM. MotoGP does this.
if (framebufferManager_->MayIntersectFramebuffer(src) || framebufferManager_->MayIntersectFramebuffer(dest)) {
if (IsOnSeparateCPUThread()) {
GPUEvent ev(GPU_EVENT_FB_MEMCPY);
ev.fb_memcpy.dst = dest;
ev.fb_memcpy.src = src;
ev.fb_memcpy.size = size;
ScheduleEvent(ev);
// This is a memcpy, so we need to wait for it to complete.
SyncThread();
} else {
PerformMemoryCopyInternal(dest, src, size);
if (!framebufferManager_->NotifyFramebufferCopy(src, dest, size, false, gstate_c.skipDrawReason)) {
// We use a little hack for Download/Upload using a VRAM mirror.
// Since they're identical we don't need to copy.
if (!Memory::IsVRAMAddress(dest) || (dest ^ 0x00400000) != src) {
Memory::Memcpy(dest, src, size);
}
}
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
return true;
}
@@ -2383,17 +2228,8 @@ bool GPUCommon::PerformMemorySet(u32 dest, u8 v, int size) {
// This may indicate a memset, usually to 0, of a framebuffer.
if (framebufferManager_->MayIntersectFramebuffer(dest)) {
Memory::Memset(dest, v, size);
if (IsOnSeparateCPUThread()) {
GPUEvent ev(GPU_EVENT_FB_MEMSET);
ev.fb_memset.dst = dest;
ev.fb_memset.v = v;
ev.fb_memset.size = size;
ScheduleEvent(ev);
// We don't need to wait for the framebuffer to be updated.
} else {
PerformMemorySetInternal(dest, v, size);
if (!framebufferManager_->NotifyFramebufferCopy(dest, dest, size, true, gstate_c.skipDrawReason)) {
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
}
return true;
}
@@ -2424,14 +2260,6 @@ bool GPUCommon::PerformMemoryUpload(u32 dest, int size) {
}
void GPUCommon::InvalidateCache(u32 addr, int size, GPUInvalidationType type) {
GPUEvent ev(GPU_EVENT_INVALIDATE_CACHE);
ev.invalidate_cache.addr = addr;
ev.invalidate_cache.size = size;
ev.invalidate_cache.type = type;
ScheduleEvent(ev);
}
void GPUCommon::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type) {
if (size > 0)
textureCache_->Invalidate(addr, size, type);
else
@@ -2456,23 +2284,12 @@ void GPUCommon::NotifyVideoUpload(u32 addr, int size, int width, int format) {
bool GPUCommon::PerformStencilUpload(u32 dest, int size) {
if (framebufferManager_->MayIntersectFramebuffer(dest)) {
if (IsOnSeparateCPUThread()) {
GPUEvent ev(GPU_EVENT_FB_STENCIL_UPLOAD);
ev.fb_stencil_upload.dst = dest;
ev.fb_stencil_upload.size = size;
ScheduleEvent(ev);
} else {
PerformStencilUploadInternal(dest, size);
}
framebufferManager_->NotifyStencilUpload(dest, size);
return true;
}
return false;
}
void GPUCommon::PerformStencilUploadInternal(u32 dest, int size) {
framebufferManager_->NotifyStencilUpload(dest, size);
}
bool GPUCommon::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) {
u32 fb_address = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.getFrameBufRawAddress() : framebufferManager_->DisplayFramebufAddr();
int fb_stride = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufStride() : framebufferManager_->DisplayFramebufStride();
+7 -115
View File
@@ -2,7 +2,6 @@
#include "Common/Common.h"
#include "Common/MemoryUtil.h"
#include "Core/ThreadEventQueue.h"
#include "GPU/GPUInterface.h"
#include "GPU/GPUState.h"
#include "GPU/Common/GPUDebugInterface.h"
@@ -15,8 +14,6 @@
#include <emmintrin.h>
#endif
typedef ThreadEventQueue<GPUInterface, GPUEvent, GPUEventType, GPU_EVENT_INVALID, GPU_EVENT_SYNC_THREAD, GPU_EVENT_FINISH_EVENT_LOOP> GPUThreadEventQueue;
class FramebufferManagerCommon;
class TextureCacheCommon;
class DrawEngineCommon;
@@ -42,7 +39,7 @@ enum {
FLAG_DIRTYONCHANGE = 64, // NOTE: Either this or FLAG_EXECUTE*, not both!
};
class GPUCommon : public GPUThreadEventQueue, public GPUDebugInterface {
class GPUCommon : public GPUInterface, public GPUDebugInterface {
public:
GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw);
virtual ~GPUCommon();
@@ -69,7 +66,7 @@ public:
void PreExecuteOp(u32 op, u32 diff) override;
bool InterpretList(DisplayList &list) override;
virtual bool ProcessDLQueue();
void ProcessDLQueue();
u32 UpdateStall(int listid, u32 newstall) override;
u32 EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer<PspGeListArgs> args, bool head) override;
u32 DequeueList(int listid) override;
@@ -77,21 +74,13 @@ public:
u32 DrawSync(int mode) override;
int GetStack(int index, u32 stackPtr) override;
void DoState(PointerWrap &p) override;
bool FramebufferDirty() override {
SyncThread();
return true;
}
bool FramebufferReallyDirty() override {
SyncThread();
return true;
}
bool BusyDrawing() override;
u32 Continue() override;
u32 Break(int mode) override;
void ReapplyGfxState() override;
void CopyDisplayToOutput() override;
void InitClear() override;
void CopyDisplayToOutput() override = 0;
void InitClear() override = 0;
bool PerformMemoryCopy(u32 dest, u32 src, int size) override;
bool PerformMemorySet(u32 dest, u8 v, int size) override;
bool PerformMemoryDownload(u32 dest, int size) override;
@@ -116,10 +105,6 @@ public:
void Execute_BoundingBox(u32 op, u32 diff);
void Execute_BlockTransferStart(u32 op, u32 diff);
void Execute_TexScaleU(u32 op, u32 diff);
void Execute_TexScaleV(u32 op, u32 diff);
void Execute_TexOffsetU(u32 op, u32 diff);
void Execute_TexOffsetV(u32 op, u32 diff);
void Execute_TexLevel(u32 op, u32 diff);
void Execute_WorldMtxNum(u32 op, u32 diff);
@@ -142,20 +127,6 @@ public:
// Note: Not virtual!
inline void Flush();
u64 GetTickEstimate() override {
#if defined(_M_X64) || defined(__ANDROID__)
return curTickEst_;
#elif defined(_M_SSE)
__m64 result = *(__m64 *)&curTickEst_;
u64 safeResult = *(u64 *)&result;
_mm_empty();
return safeResult;
#else
std::lock_guard<std::mutex> guard(curTickEstLock_);
return curTickEst_;
#endif
}
#ifdef USE_CRT_DBG
#undef new
#endif
@@ -254,11 +225,7 @@ protected:
}
}
virtual void InitClearInternal() {}
void BeginFrame() override;
virtual void BeginFrameInternal();
virtual void CopyDisplayToOutputInternal() {}
virtual void ReinitializeInternal() {}
// To avoid virtual calls to PreExecuteOp().
virtual void FastRunLoop(DisplayList &list) = 0;
@@ -268,15 +235,10 @@ protected:
void PopDLQueue();
void CheckDrawSync();
int GetNextListIndex();
void ProcessDLQueueInternal();
virtual void ReapplyGfxStateInternal();
virtual void FastLoadBoneMatrix(u32 target);
void ProcessEvent(GPUEvent ev) override;
bool ShouldExitEventLoop() override {
return coreState != CORE_RUNNING;
}
virtual void FinishDeferred() {
}
// TODO: Unify this.
virtual void FinishDeferred() {}
void DoBlockTransfer(u32 skipDrawReason);
@@ -289,53 +251,6 @@ protected:
}
}
void PerformMemoryCopyInternal(u32 dest, u32 src, int size);
void PerformMemorySetInternal(u32 dest, u8 v, int size);
void PerformStencilUploadInternal(u32 dest, int size);
void InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type);
// This mutex can be disabled, which is useful for single core mode.
class optional_mutex {
public:
optional_mutex() : enabled_(true) {}
void set_enabled(bool enabled) {
enabled_ = enabled;
}
void lock() {
if (enabled_)
mutex_.lock();
}
void unlock() {
if (enabled_)
mutex_.unlock();
}
private:
std::mutex mutex_;
bool enabled_;
};
// Allows early unlocking with a guard. Do not double unlock.
class easy_guard {
public:
easy_guard(optional_mutex &mtx) : mtx_(mtx), locked_(true) { mtx_.lock(); }
~easy_guard() {
if (locked_)
mtx_.unlock();
}
void unlock() {
if (locked_)
mtx_.unlock();
else
Crash();
locked_ = false;
}
private:
optional_mutex &mtx_;
bool locked_;
};
FramebufferManagerCommon *framebufferManager_;
TextureCacheCommon *textureCache_;
DrawEngineCommon *drawEngineCommon_;
@@ -350,7 +265,6 @@ protected:
DisplayList dls[DisplayListMaxCount];
DisplayList *currentList;
DisplayListQueue dlQueue;
optional_mutex listLock;
bool interruptRunning;
GPURunState gpuState;
@@ -372,28 +286,6 @@ protected:
GEPrimitiveType lastPrim_;
private:
// For CPU/GPU sync.
#ifdef __ANDROID__
alignas(16) std::atomic<u64> curTickEst_;
#else
alignas(16) volatile u64 curTickEst_;
std::mutex curTickEstLock_;
#endif
inline void UpdateTickEstimate(u64 value) {
#if defined(_M_X64) || defined(__ANDROID__)
curTickEst_ = value;
#elif defined(_M_SSE)
__m64 result = *(__m64 *)&value;
*(__m64 *)&curTickEst_ = result;
_mm_empty();
#else
std::lock_guard<std::mutex> guard(curTickEstLock_);
curTickEst_ = value;
#endif
}
// Debug stats.
double timeSteppingStarted_;
double timeSpentStepping_;
-58
View File
@@ -155,56 +155,6 @@ enum GPUInvalidationType {
GPU_INVALIDATE_SAFE,
};
enum GPUEventType {
GPU_EVENT_INVALID,
GPU_EVENT_PROCESS_QUEUE,
GPU_EVENT_INIT_CLEAR,
GPU_EVENT_BEGIN_FRAME,
GPU_EVENT_COPY_DISPLAY_TO_OUTPUT,
GPU_EVENT_REAPPLY_GFX_STATE,
GPU_EVENT_INVALIDATE_CACHE,
GPU_EVENT_FINISH_EVENT_LOOP,
GPU_EVENT_SYNC_THREAD,
GPU_EVENT_FB_MEMCPY,
GPU_EVENT_FB_MEMSET,
GPU_EVENT_FB_STENCIL_UPLOAD,
GPU_EVENT_REINITIALIZE,
};
struct GPUEvent {
GPUEvent(GPUEventType t) : type(t) {}
GPUEventType type;
union {
// GPU_EVENT_INVALIDATE_CACHE
struct {
u32 addr;
int size;
GPUInvalidationType type;
} invalidate_cache;
// GPU_EVENT_FB_MEMCPY
struct {
u32 dst;
u32 src;
int size;
} fb_memcpy;
// GPU_EVENT_FB_MEMSET
struct {
u32 dst;
u8 v;
int size;
} fb_memset;
// GPU_EVENT_FB_STENCIL_UPLOAD
struct {
u32 dst;
int size;
} fb_stencil_upload;
};
operator GPUEventType() const {
return type;
}
};
namespace Draw {
class DrawContext;
}
@@ -225,10 +175,6 @@ public:
virtual void BeginHostFrame() = 0;
virtual void EndHostFrame() = 0;
// Events
virtual void RunEventsUntil(u64 globalticks) = 0;
virtual void FinishEventLoop() = 0;
// Draw queue management
virtual DisplayList* getList(int listid) = 0;
// TODO: Much of this should probably be shared between the different GPU implementations.
@@ -277,9 +223,6 @@ public:
virtual void DeviceLost() = 0;
virtual void DeviceRestore() = 0;
virtual void ReapplyGfxState() = 0;
virtual void SyncThread(bool force = false) = 0;
virtual void SyncBeginFrame() = 0;
virtual u64 GetTickEstimate() = 0;
virtual void DoState(PointerWrap &p) = 0;
// Called by the window system if the window size changed. This will be reflected in PSPCoreParam.pixel*.
@@ -289,7 +232,6 @@ public:
virtual bool FramebufferDirty() = 0;
virtual bool FramebufferReallyDirty() = 0;
virtual bool BusyDrawing() = 0;
virtual void SetThreadEnabled(bool threadEnabled) = 0;
// If any jit is being used inside the GPU.
virtual bool DescribeCodePtr(const u8 *ptr, std::string &name) = 0;
+1
View File
@@ -40,6 +40,7 @@ public:
bool PerformMemoryUpload(u32 dest, int size) override;
bool PerformStencilUpload(u32 dest, int size) override;
void ClearCacheNextFrame() override {}
bool FramebufferDirty() override { return true; }
void DeviceLost() override {}
void DeviceRestore() override {}
+2 -23
View File
@@ -28,6 +28,7 @@
#include "Core/HLE/sceGe.h"
#include "Core/MIPS/MIPS.h"
#include "Core/Reporting.h"
#include "Core/Core.h"
#include "profiler/profiler.h"
#include "thin3d/thin3d.h"
@@ -280,13 +281,7 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight) {
draw_->BindIndexBuffer(nullptr, 0);
}
void SoftGPU::CopyDisplayToOutput()
{
ScheduleEvent(GPU_EVENT_COPY_DISPLAY_TO_OUTPUT);
}
void SoftGPU::CopyDisplayToOutputInternal()
{
void SoftGPU::CopyDisplayToOutput() {
// The display always shows 480x272.
CopyToCurrentFboFromDisplayRam(FB_WIDTH, FB_HEIGHT);
framebufferDirty_ = false;
@@ -301,17 +296,6 @@ void SoftGPU::CopyDisplayToOutputInternal()
}
}
void SoftGPU::ProcessEvent(GPUEvent ev) {
switch (ev.type) {
case GPU_EVENT_COPY_DISPLAY_TO_OUTPUT:
CopyDisplayToOutputInternal();
break;
default:
GPUCommon::ProcessEvent(ev);
}
}
void SoftGPU::FastRunLoop(DisplayList &list) {
PROFILE_THIS_SCOPE("soft_runloop");
for (; downcount > 0; --downcount) {
@@ -913,11 +897,6 @@ bool SoftGPU::PerformStencilUpload(u32 dest, int size)
}
bool SoftGPU::FramebufferDirty() {
if (g_Config.bSeparateCPUThread) {
// Allow it to process fully before deciding if it's dirty.
SyncThread();
}
if (g_Config.iFrameSkip != 0) {
bool dirty = framebufferDirty_;
framebufferDirty_ = false;
-3
View File
@@ -94,12 +94,9 @@ public:
protected:
void FastRunLoop(DisplayList &list) override;
void ProcessEvent(GPUEvent ev) override;
void CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight);
private:
void CopyDisplayToOutputInternal() override;
bool framebufferDirty_;
u32 displayFramebuf_;
u32 displayStride_;
+5 -19
View File
@@ -332,21 +332,17 @@ void GPU_Vulkan::BuildReportingInfo() {
Reporting::UpdateConfig();
}
void GPU_Vulkan::ReinitializeInternal() {
void GPU_Vulkan::Reinitialize() {
GPUCommon::Reinitialize();
textureCacheVulkan_->Clear(true);
depalShaderCache_.Clear();
framebufferManagerVulkan_->DestroyAllFBOs();
}
void GPU_Vulkan::InitClearInternal() {
void GPU_Vulkan::InitClear() {
bool useNonBufferedRendering = g_Config.iRenderingMode == FB_NON_BUFFERED_MODE;
if (useNonBufferedRendering) {
/*
glstate.depthWrite.set(GL_TRUE);
glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
*/
// TODO?
}
}
@@ -370,11 +366,6 @@ void GPU_Vulkan::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat
}
bool GPU_Vulkan::FramebufferDirty() {
if (ThreadEnabled()) {
// Allow it to process fully before deciding if it's dirty.
SyncThread();
}
VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB();
if (vfb) {
bool dirty = vfb->dirtyAfterDisplay;
@@ -385,11 +376,6 @@ bool GPU_Vulkan::FramebufferDirty() {
}
bool GPU_Vulkan::FramebufferReallyDirty() {
if (ThreadEnabled()) {
// Allow it to process fully before deciding if it's dirty.
SyncThread();
}
VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB();
if (vfb) {
bool dirty = vfb->reallyDirtyAfterDisplay;
@@ -399,7 +385,7 @@ bool GPU_Vulkan::FramebufferReallyDirty() {
return true;
}
void GPU_Vulkan::CopyDisplayToOutputInternal() {
void GPU_Vulkan::CopyDisplayToOutput() {
// Flush anything left over.
drawEngine_.Flush();
+3 -3
View File
@@ -96,9 +96,9 @@ private:
}
void CheckFlushOp(int cmd, u32 diff);
void BuildReportingInfo();
void InitClearInternal() override;
void CopyDisplayToOutputInternal() override;
void ReinitializeInternal() override;
void InitClear() override;
void CopyDisplayToOutput() override;
void Reinitialize() override;
inline void UpdateVsyncInterval(bool force);
void UpdateCmdInfo();
-7
View File
@@ -661,13 +661,6 @@ void GameSettingsScreen::CreateViews() {
systemSettings->Add(new CheckBox(&g_Config.bFastMemory, sy->T("Fast Memory", "Fast Memory (Unstable)")))->OnClick.Handle(this, &GameSettingsScreen::OnJitAffectingSetting);
auto separateCPUThread = new CheckBox(&g_Config.bSeparateCPUThread, sy->T("Multithreaded (experimental)"));
systemSettings->Add(separateCPUThread);
separateCPUThread->OnClick.Add([=](EventParams &e) {
if (g_Config.bSeparateCPUThread)
settingInfo_->Show(sy->T("Multithreaded Tip", "Not always faster, causes glitches/crashing"), e.v);
return UI::EVENT_CONTINUE;
});
systemSettings->Add(new CheckBox(&g_Config.bSeparateIOThread, sy->T("I/O on thread (experimental)")))->SetEnabled(!PSP_IsInited());
static const char *ioTimingMethods[] = { "Fast (lag on slow storage)", "Host (bugs, less lag)", "Simulate UMD delays" };
View *ioTimingMethod = systemSettings->Add(new PopupMultiChoice(&g_Config.iIOTimingMethod, sy->T("IO timing method"), ioTimingMethods, 0, ARRAY_SIZE(ioTimingMethods), sy->GetName(), screenManager()));
+1 -1
View File
@@ -12,7 +12,7 @@
#endif
// TODO: Using a thread here is unfinished and does not work correctly.
const bool useThread = false;
const bool useThread = true;
#ifndef UINT64_MAX
#define UINT64_MAX 0xFFFFFFFFFFFFFFFFULL