2012-12-28 21:58:00 +01:00
|
|
|
#pragma once
|
|
|
|
|
2013-08-12 08:40:36 -07:00
|
|
|
#include "Common/Common.h"
|
2013-10-26 18:11:17 -07:00
|
|
|
#include "Common/MemoryUtil.h"
|
2013-08-10 09:08:31 -07:00
|
|
|
#include "Core/ThreadEventQueue.h"
|
2013-08-07 23:27:29 -07:00
|
|
|
#include "GPU/GPUInterface.h"
|
2013-09-22 00:18:46 -07:00
|
|
|
#include "GPU/Common/GPUDebugInterface.h"
|
2012-12-28 21:58:00 +01:00
|
|
|
|
2013-08-12 08:51:19 -07:00
|
|
|
#if defined(ANDROID)
|
|
|
|
#include <atomic>
|
|
|
|
#elif defined(_M_SSE)
|
2013-08-12 08:40:36 -07:00
|
|
|
#include <xmmintrin.h>
|
|
|
|
#endif
|
|
|
|
|
2013-08-10 03:33:09 -07:00
|
|
|
typedef ThreadEventQueue<GPUInterface, GPUEvent, GPUEventType, GPU_EVENT_INVALID, GPU_EVENT_SYNC_THREAD, GPU_EVENT_FINISH_EVENT_LOOP> GPUThreadEventQueue;
|
|
|
|
|
2013-09-22 10:22:33 -07:00
|
|
|
class GPUCommon : public GPUThreadEventQueue, public GPUDebugInterface
|
2012-12-28 21:58:00 +01:00
|
|
|
{
|
|
|
|
public:
|
2013-04-04 23:19:28 -07:00
|
|
|
GPUCommon();
|
|
|
|
virtual ~GPUCommon() {}
|
2013-11-28 15:34:41 -08:00
|
|
|
virtual void Reinitialize();
|
2012-12-29 02:10:29 +01:00
|
|
|
|
2013-04-06 08:19:54 -07:00
|
|
|
virtual void InterruptStart(int listid);
|
|
|
|
virtual void InterruptEnd(int listid);
|
2014-03-29 16:51:38 -07:00
|
|
|
virtual void SyncEnd(GPUSyncType waitType, int listid, bool wokeThreads);
|
2013-03-31 23:02:46 -07:00
|
|
|
virtual void EnableInterrupts(bool enable) {
|
|
|
|
interruptsEnabled_ = enable;
|
|
|
|
}
|
2013-02-04 00:41:16 +01:00
|
|
|
|
2013-03-31 23:02:46 -07:00
|
|
|
virtual void ExecuteOp(u32 op, u32 diff);
|
2012-12-29 02:10:29 +01:00
|
|
|
virtual void PreExecuteOp(u32 op, u32 diff);
|
|
|
|
virtual bool InterpretList(DisplayList &list);
|
|
|
|
virtual bool ProcessDLQueue();
|
2013-03-31 23:23:03 -07:00
|
|
|
virtual u32 UpdateStall(int listid, u32 newstall);
|
2013-09-20 09:42:09 -07:00
|
|
|
virtual u32 EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer<PspGeListArgs> args, bool head);
|
2013-03-31 23:23:03 -07:00
|
|
|
virtual u32 DequeueList(int listid);
|
|
|
|
virtual int ListSync(int listid, int mode);
|
|
|
|
virtual u32 DrawSync(int mode);
|
2013-09-21 10:03:49 -07:00
|
|
|
virtual int GetStack(int index, u32 stackPtr);
|
2012-12-29 11:41:33 -08:00
|
|
|
virtual void DoState(PointerWrap &p);
|
2013-08-10 18:45:07 -07:00
|
|
|
virtual bool FramebufferDirty() {
|
|
|
|
SyncThread();
|
|
|
|
return true;
|
|
|
|
}
|
2013-08-16 01:00:26 +02:00
|
|
|
virtual bool FramebufferReallyDirty() {
|
|
|
|
SyncThread();
|
|
|
|
return true;
|
|
|
|
}
|
2013-09-21 19:31:54 -07:00
|
|
|
virtual bool BusyDrawing();
|
2013-03-31 23:23:03 -07:00
|
|
|
virtual u32 Continue();
|
|
|
|
virtual u32 Break(int mode);
|
2013-08-04 15:15:50 -07:00
|
|
|
virtual void ReapplyGfxState();
|
2012-12-28 21:58:00 +01:00
|
|
|
|
2014-04-16 08:12:21 -07:00
|
|
|
void Execute_OffsetAddr(u32 op, u32 diff);
|
|
|
|
void Execute_Origin(u32 op, u32 diff);
|
|
|
|
void Execute_Jump(u32 op, u32 diff);
|
|
|
|
void Execute_BJump(u32 op, u32 diff);
|
|
|
|
void Execute_Call(u32 op, u32 diff);
|
|
|
|
void Execute_Ret(u32 op, u32 diff);
|
|
|
|
void Execute_End(u32 op, u32 diff);
|
|
|
|
|
2013-08-11 13:41:42 -07:00
|
|
|
virtual u64 GetTickEstimate() {
|
2013-08-12 08:51:19 -07:00
|
|
|
#if defined(_M_X64) || defined(ANDROID)
|
2013-08-12 08:40:36 -07:00
|
|
|
return curTickEst_;
|
|
|
|
#elif defined(_M_SSE)
|
|
|
|
__m64 result = *(__m64 *)&curTickEst_;
|
2013-08-13 01:01:40 -07:00
|
|
|
u64 safeResult = *(u64 *)&result;
|
|
|
|
_mm_empty();
|
|
|
|
return safeResult;
|
2013-08-12 08:40:36 -07:00
|
|
|
#else
|
2013-08-11 13:41:42 -07:00
|
|
|
lock_guard guard(curTickEstLock_);
|
|
|
|
return curTickEst_;
|
2013-08-12 08:40:36 -07:00
|
|
|
#endif
|
2013-08-11 13:41:42 -07:00
|
|
|
}
|
|
|
|
|
2013-10-26 18:11:17 -07:00
|
|
|
void *operator new(size_t s) {
|
|
|
|
return AllocateAlignedMemory(s, 16);
|
|
|
|
}
|
|
|
|
void operator delete(void *p) {
|
|
|
|
FreeAlignedMemory(p);
|
|
|
|
}
|
|
|
|
|
2013-11-30 18:39:16 -08:00
|
|
|
virtual bool DescribeCodePtr(const u8 *ptr, std::string &name) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-06-14 08:42:18 -07:00
|
|
|
// From GPUDebugInterface.
|
|
|
|
virtual bool GetCurrentDisplayList(DisplayList &list);
|
|
|
|
virtual std::vector<DisplayList> ActiveDisplayLists();
|
|
|
|
virtual void ResetListPC(int listID, u32 pc);
|
|
|
|
virtual void ResetListStall(int listID, u32 stall);
|
|
|
|
virtual void ResetListState(int listID, DisplayListState state);
|
|
|
|
|
|
|
|
virtual GPUDebugOp DissassembleOp(u32 pc, u32 op);
|
|
|
|
virtual std::vector<GPUDebugOp> DissassembleOpRange(u32 startpc, u32 endpc);
|
|
|
|
|
|
|
|
virtual void NotifySteppingEnter();
|
|
|
|
virtual void NotifySteppingExit();
|
|
|
|
|
|
|
|
virtual u32 GetRelativeAddress(u32 data);
|
|
|
|
virtual u32 GetVertexAddress();
|
|
|
|
virtual u32 GetIndexAddress();
|
|
|
|
virtual GPUgstate GetGState();
|
|
|
|
virtual void SetCmdValue(u32 op);
|
|
|
|
|
|
|
|
virtual DisplayList* getList(int listid) {
|
|
|
|
return &dls[listid];
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::list<int>& GetDisplayLists() {
|
|
|
|
return dlQueue;
|
|
|
|
}
|
2015-01-17 11:57:07 -08:00
|
|
|
virtual bool DecodeTexture(u8* dest, const GPUgstate &state) {
|
2014-06-14 08:42:18 -07:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
std::vector<FramebufferInfo> GetFramebufferList() {
|
|
|
|
return std::vector<FramebufferInfo>();
|
|
|
|
}
|
|
|
|
virtual void ClearShaderCache() {}
|
2014-06-22 21:42:29 -07:00
|
|
|
virtual void CleanupBeforeUI() {}
|
2014-06-14 08:42:18 -07:00
|
|
|
|
2012-12-28 21:58:00 +01:00
|
|
|
protected:
|
2013-04-28 14:23:30 -07:00
|
|
|
// To avoid virtual calls to PreExecuteOp().
|
|
|
|
virtual void FastRunLoop(DisplayList &list) = 0;
|
|
|
|
void SlowRunLoop(DisplayList &list);
|
2014-04-05 12:04:10 -07:00
|
|
|
void UpdatePC(u32 currentPC, u32 newPC);
|
|
|
|
void UpdatePC(u32 currentPC) {
|
|
|
|
UpdatePC(currentPC, currentPC);
|
|
|
|
}
|
2013-04-28 13:34:29 -07:00
|
|
|
void UpdateState(GPUState state);
|
2013-04-04 23:19:28 -07:00
|
|
|
void PopDLQueue();
|
|
|
|
void CheckDrawSync();
|
2013-08-04 16:31:11 -07:00
|
|
|
int GetNextListIndex();
|
2013-08-07 23:59:32 -07:00
|
|
|
void ProcessDLQueueInternal();
|
|
|
|
void ReapplyGfxStateInternal();
|
2014-03-02 18:12:40 -08:00
|
|
|
virtual void FastLoadBoneMatrix(u32 target);
|
2013-08-10 03:33:09 -07:00
|
|
|
virtual void ProcessEvent(GPUEvent ev);
|
2013-08-11 11:40:41 -07:00
|
|
|
virtual bool ShouldExitEventLoop() {
|
|
|
|
return coreState != CORE_RUNNING;
|
|
|
|
}
|
2015-03-14 18:11:00 -07:00
|
|
|
virtual void FinishDeferred() {
|
|
|
|
}
|
2013-04-03 08:10:35 -07:00
|
|
|
|
2013-08-09 01:03:54 -07:00
|
|
|
// Allows early unlocking with a guard. Do not double unlock.
|
2013-08-09 00:32:40 -07:00
|
|
|
class easy_guard {
|
|
|
|
public:
|
|
|
|
easy_guard(recursive_mutex &mtx) : mtx_(mtx), locked_(true) { mtx_.lock(); }
|
|
|
|
~easy_guard() { if (locked_) mtx_.unlock(); }
|
2013-08-09 01:03:54 -07:00
|
|
|
void unlock() { if (locked_) mtx_.unlock(); else Crash(); locked_ = false; }
|
2013-08-09 00:32:40 -07:00
|
|
|
|
|
|
|
private:
|
|
|
|
recursive_mutex &mtx_;
|
2013-08-10 18:38:47 +02:00
|
|
|
bool locked_;
|
2013-08-09 00:32:40 -07:00
|
|
|
};
|
|
|
|
|
2013-04-04 23:19:28 -07:00
|
|
|
typedef std::list<int> DisplayListQueue;
|
2012-12-29 02:10:29 +01:00
|
|
|
|
2013-09-21 13:18:20 -07:00
|
|
|
int nextListID;
|
2013-04-04 23:19:28 -07:00
|
|
|
DisplayList dls[DisplayListMaxCount];
|
2012-12-28 21:58:00 +01:00
|
|
|
DisplayList *currentList;
|
|
|
|
DisplayListQueue dlQueue;
|
2013-08-07 23:27:29 -07:00
|
|
|
recursive_mutex listLock;
|
2012-12-29 02:10:29 +01:00
|
|
|
|
2013-02-04 00:41:16 +01:00
|
|
|
bool interruptRunning;
|
2013-04-04 01:07:30 -07:00
|
|
|
GPUState gpuState;
|
2013-04-04 00:35:38 -07:00
|
|
|
bool isbreak;
|
2013-04-07 12:45:42 -07:00
|
|
|
u64 drawCompleteTicks;
|
2013-04-09 00:56:04 -07:00
|
|
|
u64 busyTicks;
|
2012-12-29 02:10:29 +01:00
|
|
|
|
2013-04-28 14:23:30 -07:00
|
|
|
int downcount;
|
2013-04-03 08:10:35 -07:00
|
|
|
u64 startingTicks;
|
|
|
|
u32 cycleLastPC;
|
|
|
|
int cyclesExecuted;
|
|
|
|
|
2012-12-29 02:10:29 +01:00
|
|
|
bool dumpNextFrame_;
|
|
|
|
bool dumpThisFrame_;
|
2013-03-31 23:02:46 -07:00
|
|
|
bool interruptsEnabled_;
|
2013-02-04 00:41:16 +01:00
|
|
|
|
2013-08-13 21:42:48 -07:00
|
|
|
private:
|
2013-08-11 13:41:42 -07:00
|
|
|
// For CPU/GPU sync.
|
2013-08-12 08:51:19 -07:00
|
|
|
#ifdef ANDROID
|
|
|
|
std::atomic<u64> curTickEst_;
|
|
|
|
#else
|
2013-08-12 08:40:36 -07:00
|
|
|
volatile MEMORY_ALIGNED16(u64) curTickEst_;
|
2013-08-11 13:41:42 -07:00
|
|
|
recursive_mutex curTickEstLock_;
|
2013-08-12 08:51:19 -07:00
|
|
|
#endif
|
2013-08-11 13:41:42 -07:00
|
|
|
|
2013-08-13 21:42:48 -07:00
|
|
|
inline void UpdateTickEstimate(u64 value) {
|
2013-08-12 08:51:19 -07:00
|
|
|
#if defined(_M_X64) || defined(ANDROID)
|
2013-08-12 08:40:36 -07:00
|
|
|
curTickEst_ = value;
|
|
|
|
#elif defined(_M_SSE)
|
|
|
|
__m64 result = *(__m64 *)&value;
|
|
|
|
*(__m64 *)&curTickEst_ = result;
|
2013-08-13 01:01:40 -07:00
|
|
|
_mm_empty();
|
2013-08-12 08:40:36 -07:00
|
|
|
#else
|
2013-08-11 13:41:42 -07:00
|
|
|
lock_guard guard(curTickEstLock_);
|
|
|
|
curTickEst_ = value;
|
2013-08-12 08:40:36 -07:00
|
|
|
#endif
|
2013-08-11 13:41:42 -07:00
|
|
|
}
|
|
|
|
|
2014-06-14 08:42:18 -07:00
|
|
|
// Debug stats.
|
|
|
|
double timeSteppingStarted_;
|
|
|
|
double timeSpentStepping_;
|
2013-02-04 00:41:16 +01:00
|
|
|
};
|