mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-24 03:39:07 +02:00
Merge pull request #10056 from hrydgard/remove-multithreading-2
Remove the old style multithreading
This commit is contained in:
22 files changed
+98
-564
No files matched your search
@@ -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),
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 @@ 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
@@ -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);
|
||||
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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_;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user