2012-12-28 20:58:00 +00:00
|
|
|
#pragma once
|
|
|
|
|
2013-08-12 15:40:36 +00:00
|
|
|
#include "Common/Common.h"
|
2013-10-27 01:11:17 +00:00
|
|
|
#include "Common/MemoryUtil.h"
|
2013-08-10 16:08:31 +00:00
|
|
|
#include "Core/ThreadEventQueue.h"
|
2013-08-08 06:27:29 +00:00
|
|
|
#include "GPU/GPUInterface.h"
|
2017-01-28 10:39:34 +00:00
|
|
|
#include "GPU/GPUState.h"
|
2013-09-22 07:18:46 +00:00
|
|
|
#include "GPU/Common/GPUDebugInterface.h"
|
2012-12-28 20:58:00 +00:00
|
|
|
|
2016-10-12 09:13:16 +00:00
|
|
|
#if defined(__ANDROID__)
|
2013-08-12 15:51:19 +00:00
|
|
|
#include <atomic>
|
|
|
|
#elif defined(_M_SSE)
|
2013-08-12 15:40:36 +00:00
|
|
|
#include <xmmintrin.h>
|
|
|
|
#endif
|
|
|
|
|
2013-08-10 10:33:09 +00:00
|
|
|
typedef ThreadEventQueue<GPUInterface, GPUEvent, GPUEventType, GPU_EVENT_INVALID, GPU_EVENT_SYNC_THREAD, GPU_EVENT_FINISH_EVENT_LOOP> GPUThreadEventQueue;
|
|
|
|
|
2016-12-21 17:07:17 +00:00
|
|
|
class FramebufferManagerCommon;
|
|
|
|
class TextureCacheCommon;
|
2017-01-21 19:42:40 +00:00
|
|
|
class DrawEngineCommon;
|
2017-01-30 15:50:35 +00:00
|
|
|
class GraphicsContext;
|
|
|
|
namespace Draw {
|
|
|
|
class DrawContext;
|
|
|
|
}
|
2016-12-21 17:07:17 +00:00
|
|
|
|
2017-01-28 10:39:34 +00:00
|
|
|
enum DrawType {
|
|
|
|
DRAW_UNKNOWN,
|
|
|
|
DRAW_PRIM,
|
|
|
|
DRAW_SPLINE,
|
|
|
|
DRAW_BEZIER,
|
|
|
|
};
|
|
|
|
|
2015-07-26 20:38:40 +00:00
|
|
|
class GPUCommon : public GPUThreadEventQueue, public GPUDebugInterface {
|
2012-12-28 20:58:00 +00:00
|
|
|
public:
|
2017-01-30 15:50:35 +00:00
|
|
|
GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw);
|
2015-07-26 20:38:40 +00:00
|
|
|
virtual ~GPUCommon();
|
2015-09-05 19:23:58 +00:00
|
|
|
|
2017-02-06 10:55:54 +00:00
|
|
|
Draw::DrawContext *GetDrawContext() override {
|
|
|
|
return draw_;
|
|
|
|
}
|
2015-10-14 20:18:29 +00:00
|
|
|
void Reinitialize() override;
|
2012-12-29 01:10:29 +00:00
|
|
|
|
2016-01-06 22:53:21 +00:00
|
|
|
void BeginHostFrame() override;
|
|
|
|
void EndHostFrame() override;
|
|
|
|
|
2015-10-14 20:18:29 +00:00
|
|
|
void InterruptStart(int listid) override;
|
|
|
|
void InterruptEnd(int listid) override;
|
|
|
|
void SyncEnd(GPUSyncType waitType, int listid, bool wokeThreads) override;
|
|
|
|
void EnableInterrupts(bool enable) override {
|
2013-04-01 06:02:46 +00:00
|
|
|
interruptsEnabled_ = enable;
|
|
|
|
}
|
2013-02-03 23:41:16 +00:00
|
|
|
|
2016-12-21 17:13:58 +00:00
|
|
|
void Resized() override;
|
|
|
|
|
2015-10-14 20:18:29 +00:00
|
|
|
void ExecuteOp(u32 op, u32 diff) override;
|
|
|
|
void PreExecuteOp(u32 op, u32 diff) override;
|
2017-01-24 09:44:02 +00:00
|
|
|
|
2015-10-14 20:18:29 +00:00
|
|
|
bool InterpretList(DisplayList &list) override;
|
2012-12-29 01:10:29 +00:00
|
|
|
virtual bool ProcessDLQueue();
|
2015-10-14 20:18:29 +00:00
|
|
|
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;
|
|
|
|
int ListSync(int listid, int mode) override;
|
|
|
|
u32 DrawSync(int mode) override;
|
|
|
|
int GetStack(int index, u32 stackPtr) override;
|
|
|
|
void DoState(PointerWrap &p) override;
|
|
|
|
bool FramebufferDirty() override {
|
2013-08-11 01:45:07 +00:00
|
|
|
SyncThread();
|
|
|
|
return true;
|
|
|
|
}
|
2015-10-14 20:18:29 +00:00
|
|
|
bool FramebufferReallyDirty() override {
|
2013-08-15 23:00:26 +00:00
|
|
|
SyncThread();
|
|
|
|
return true;
|
|
|
|
}
|
2015-10-14 20:18:29 +00:00
|
|
|
bool BusyDrawing() override;
|
|
|
|
u32 Continue() override;
|
|
|
|
u32 Break(int mode) override;
|
|
|
|
void ReapplyGfxState() override;
|
2012-12-28 20:58:00 +00:00
|
|
|
|
2016-12-21 17:51:19 +00:00
|
|
|
void CopyDisplayToOutput() override;
|
|
|
|
void InitClear() override;
|
2016-12-21 17:26:06 +00:00
|
|
|
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;
|
|
|
|
bool PerformMemoryUpload(u32 dest, int size) override;
|
|
|
|
|
2016-12-21 17:33:08 +00:00
|
|
|
void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override;
|
|
|
|
void NotifyVideoUpload(u32 addr, int size, int width, int format) override;
|
|
|
|
bool PerformStencilUpload(u32 dest, int size) override;
|
|
|
|
|
2014-04-16 15:12:21 +00:00
|
|
|
void Execute_OffsetAddr(u32 op, u32 diff);
|
2017-01-28 10:53:28 +00:00
|
|
|
void Execute_Vaddr(u32 op, u32 diff);
|
|
|
|
void Execute_Iaddr(u32 op, u32 diff);
|
2014-04-16 15:12:21 +00:00
|
|
|
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);
|
|
|
|
|
2017-01-21 19:42:40 +00:00
|
|
|
void Execute_Bezier(u32 op, u32 diff);
|
|
|
|
void Execute_Spline(u32 op, u32 diff);
|
|
|
|
void Execute_BoundingBox(u32 op, u32 diff);
|
2017-01-23 15:57:16 +00:00
|
|
|
void Execute_BlockTransferStart(u32 op, u32 diff);
|
2017-01-21 19:42:40 +00:00
|
|
|
|
2017-01-28 10:39:34 +00:00
|
|
|
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);
|
2017-02-13 21:02:26 +00:00
|
|
|
void Execute_TexLevel(u32 op, u32 diff);
|
2017-01-28 10:39:34 +00:00
|
|
|
|
2017-01-23 19:56:25 +00:00
|
|
|
void Execute_WorldMtxNum(u32 op, u32 diff);
|
|
|
|
void Execute_WorldMtxData(u32 op, u32 diff);
|
|
|
|
void Execute_ViewMtxNum(u32 op, u32 diff);
|
|
|
|
void Execute_ViewMtxData(u32 op, u32 diff);
|
|
|
|
void Execute_ProjMtxNum(u32 op, u32 diff);
|
|
|
|
void Execute_ProjMtxData(u32 op, u32 diff);
|
|
|
|
void Execute_TgenMtxNum(u32 op, u32 diff);
|
|
|
|
void Execute_TgenMtxData(u32 op, u32 diff);
|
|
|
|
void Execute_BoneMtxNum(u32 op, u32 diff);
|
|
|
|
void Execute_BoneMtxData(u32 op, u32 diff);
|
|
|
|
|
2017-01-24 09:44:02 +00:00
|
|
|
void Execute_MorphWeight(u32 op, u32 diff);
|
|
|
|
|
|
|
|
void Execute_Unknown(u32 op, u32 diff);
|
|
|
|
|
2017-01-23 20:00:44 +00:00
|
|
|
int EstimatePerVertexCost();
|
|
|
|
|
2017-01-23 19:56:25 +00:00
|
|
|
// Note: Not virtual!
|
|
|
|
inline void Flush();
|
|
|
|
|
2015-10-14 20:18:29 +00:00
|
|
|
u64 GetTickEstimate() override {
|
2016-10-12 09:13:16 +00:00
|
|
|
#if defined(_M_X64) || defined(__ANDROID__)
|
2013-08-12 15:40:36 +00:00
|
|
|
return curTickEst_;
|
|
|
|
#elif defined(_M_SSE)
|
|
|
|
__m64 result = *(__m64 *)&curTickEst_;
|
2013-08-13 08:01:40 +00:00
|
|
|
u64 safeResult = *(u64 *)&result;
|
|
|
|
_mm_empty();
|
|
|
|
return safeResult;
|
2013-08-12 15:40:36 +00:00
|
|
|
#else
|
2013-08-11 20:41:42 +00:00
|
|
|
lock_guard guard(curTickEstLock_);
|
|
|
|
return curTickEst_;
|
2013-08-12 15:40:36 +00:00
|
|
|
#endif
|
2013-08-11 20:41:42 +00:00
|
|
|
}
|
|
|
|
|
2016-02-10 14:22:28 +00:00
|
|
|
#ifdef USE_CRT_DBG
|
|
|
|
#undef new
|
|
|
|
#endif
|
2013-10-27 01:11:17 +00:00
|
|
|
void *operator new(size_t s) {
|
|
|
|
return AllocateAlignedMemory(s, 16);
|
|
|
|
}
|
|
|
|
void operator delete(void *p) {
|
|
|
|
FreeAlignedMemory(p);
|
|
|
|
}
|
2016-02-10 14:22:28 +00:00
|
|
|
#ifdef USE_CRT_DBG
|
|
|
|
#define new DBG_NEW
|
|
|
|
#endif
|
2013-10-27 01:11:17 +00:00
|
|
|
|
2015-10-14 20:18:29 +00:00
|
|
|
bool DescribeCodePtr(const u8 *ptr, std::string &name) override {
|
2013-12-01 02:39:16 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-06-14 15:42:18 +00:00
|
|
|
// From GPUDebugInterface.
|
2015-10-14 20:18:29 +00:00
|
|
|
bool GetCurrentDisplayList(DisplayList &list) override;
|
2017-02-14 11:42:35 +00:00
|
|
|
bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) override;
|
|
|
|
bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer) override;
|
|
|
|
bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) override;
|
2017-02-17 23:43:02 +00:00
|
|
|
bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override;
|
2017-02-14 11:42:35 +00:00
|
|
|
|
2015-10-14 20:18:29 +00:00
|
|
|
std::vector<DisplayList> ActiveDisplayLists() override;
|
|
|
|
void ResetListPC(int listID, u32 pc) override;
|
|
|
|
void ResetListStall(int listID, u32 stall) override;
|
|
|
|
void ResetListState(int listID, DisplayListState state) override;
|
2014-06-14 15:42:18 +00:00
|
|
|
|
2015-10-14 20:18:29 +00:00
|
|
|
GPUDebugOp DissassembleOp(u32 pc, u32 op) override;
|
|
|
|
std::vector<GPUDebugOp> DissassembleOpRange(u32 startpc, u32 endpc) override;
|
2014-06-14 15:42:18 +00:00
|
|
|
|
2015-10-14 20:18:29 +00:00
|
|
|
void NotifySteppingEnter() override;
|
|
|
|
void NotifySteppingExit() override;
|
2014-06-14 15:42:18 +00:00
|
|
|
|
2015-10-14 20:18:29 +00:00
|
|
|
u32 GetRelativeAddress(u32 data) override;
|
|
|
|
u32 GetVertexAddress() override;
|
|
|
|
u32 GetIndexAddress() override;
|
|
|
|
GPUgstate GetGState() override;
|
|
|
|
void SetCmdValue(u32 op) override;
|
2014-06-14 15:42:18 +00:00
|
|
|
|
2015-10-14 20:18:29 +00:00
|
|
|
DisplayList* getList(int listid) override {
|
2014-06-14 15:42:18 +00:00
|
|
|
return &dls[listid];
|
|
|
|
}
|
|
|
|
|
2015-10-14 20:18:29 +00:00
|
|
|
const std::list<int>& GetDisplayLists() override {
|
2014-06-14 15:42:18 +00:00
|
|
|
return dlQueue;
|
|
|
|
}
|
2015-10-14 20:18:29 +00:00
|
|
|
virtual bool DecodeTexture(u8* dest, const GPUgstate &state) override {
|
2014-06-14 15:42:18 +00:00
|
|
|
return false;
|
|
|
|
}
|
2015-10-14 20:18:29 +00:00
|
|
|
std::vector<FramebufferInfo> GetFramebufferList() override {
|
2014-06-14 15:42:18 +00:00
|
|
|
return std::vector<FramebufferInfo>();
|
|
|
|
}
|
2015-10-14 20:18:29 +00:00
|
|
|
void ClearShaderCache() override {}
|
|
|
|
void CleanupBeforeUI() override {}
|
2014-06-14 15:42:18 +00:00
|
|
|
|
2015-10-14 15:45:21 +00:00
|
|
|
std::vector<std::string> DebugGetShaderIDs(DebugShaderType shader) override { return std::vector<std::string>(); };
|
|
|
|
std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override {
|
|
|
|
return "N/A";
|
|
|
|
}
|
|
|
|
|
2012-12-28 20:58:00 +00:00
|
|
|
protected:
|
2017-01-28 10:39:34 +00:00
|
|
|
void SetDrawType(DrawType type) {
|
|
|
|
if (type != lastDraw_) {
|
|
|
|
gstate_c.Dirty(DIRTY_UVSCALEOFFSET);
|
|
|
|
lastDraw_ = type;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-21 18:58:10 +00:00
|
|
|
virtual void InitClearInternal() {}
|
|
|
|
virtual void BeginFrameInternal() {}
|
|
|
|
virtual void CopyDisplayToOutputInternal() {}
|
|
|
|
virtual void ReinitializeInternal() {}
|
|
|
|
|
2013-04-28 21:23:30 +00:00
|
|
|
// To avoid virtual calls to PreExecuteOp().
|
|
|
|
virtual void FastRunLoop(DisplayList &list) = 0;
|
|
|
|
void SlowRunLoop(DisplayList &list);
|
2014-04-05 19:04:10 +00:00
|
|
|
void UpdatePC(u32 currentPC, u32 newPC);
|
|
|
|
void UpdatePC(u32 currentPC) {
|
|
|
|
UpdatePC(currentPC, currentPC);
|
|
|
|
}
|
2015-07-26 20:38:40 +00:00
|
|
|
void UpdateState(GPURunState state);
|
2013-04-05 06:19:28 +00:00
|
|
|
void PopDLQueue();
|
|
|
|
void CheckDrawSync();
|
2013-08-04 23:31:11 +00:00
|
|
|
int GetNextListIndex();
|
2013-08-08 06:59:32 +00:00
|
|
|
void ProcessDLQueueInternal();
|
2015-09-06 10:23:14 +00:00
|
|
|
virtual void ReapplyGfxStateInternal();
|
2014-03-03 02:12:40 +00:00
|
|
|
virtual void FastLoadBoneMatrix(u32 target);
|
2015-10-14 20:18:29 +00:00
|
|
|
void ProcessEvent(GPUEvent ev) override;
|
|
|
|
bool ShouldExitEventLoop() override {
|
2013-08-11 18:40:41 +00:00
|
|
|
return coreState != CORE_RUNNING;
|
|
|
|
}
|
2015-03-15 01:11:00 +00:00
|
|
|
virtual void FinishDeferred() {
|
|
|
|
}
|
2013-04-03 15:10:35 +00:00
|
|
|
|
2016-12-21 17:07:17 +00:00
|
|
|
void DoBlockTransfer(u32 skipDrawReason);
|
|
|
|
|
2016-04-10 20:07:08 +00:00
|
|
|
void AdvanceVerts(u32 vertType, int count, int bytesRead);
|
|
|
|
|
2016-12-21 17:33:08 +00:00
|
|
|
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);
|
|
|
|
|
2013-08-09 08:03:54 +00:00
|
|
|
// Allows early unlocking with a guard. Do not double unlock.
|
2013-08-09 07:32:40 +00:00
|
|
|
class easy_guard {
|
|
|
|
public:
|
2017-01-27 09:17:44 +00:00
|
|
|
easy_guard(optional_recursive_mutex &mtx) : mtx_(mtx), locked_(true) { mtx_.lock(); }
|
|
|
|
~easy_guard() {
|
|
|
|
if (locked_)
|
|
|
|
mtx_.unlock();
|
|
|
|
}
|
|
|
|
void unlock() {
|
|
|
|
if (locked_)
|
|
|
|
mtx_.unlock();
|
|
|
|
else
|
|
|
|
Crash();
|
|
|
|
locked_ = false;
|
|
|
|
}
|
2013-08-09 07:32:40 +00:00
|
|
|
|
|
|
|
private:
|
2017-01-27 09:17:44 +00:00
|
|
|
optional_recursive_mutex &mtx_;
|
2013-08-10 16:38:47 +00:00
|
|
|
bool locked_;
|
2013-08-09 07:32:40 +00:00
|
|
|
};
|
|
|
|
|
2016-12-21 17:07:17 +00:00
|
|
|
FramebufferManagerCommon *framebufferManager_;
|
|
|
|
TextureCacheCommon *textureCache_;
|
2017-01-21 19:42:40 +00:00
|
|
|
DrawEngineCommon *drawEngineCommon_;
|
2017-01-23 19:48:23 +00:00
|
|
|
ShaderManagerCommon *shaderManager_;
|
2016-12-21 17:07:17 +00:00
|
|
|
|
2017-01-30 15:50:35 +00:00
|
|
|
GraphicsContext *gfxCtx_;
|
|
|
|
Draw::DrawContext *draw_;
|
|
|
|
|
2013-04-05 06:19:28 +00:00
|
|
|
typedef std::list<int> DisplayListQueue;
|
2012-12-29 01:10:29 +00:00
|
|
|
|
2013-09-21 20:18:20 +00:00
|
|
|
int nextListID;
|
2013-04-05 06:19:28 +00:00
|
|
|
DisplayList dls[DisplayListMaxCount];
|
2012-12-28 20:58:00 +00:00
|
|
|
DisplayList *currentList;
|
|
|
|
DisplayListQueue dlQueue;
|
2017-01-27 09:17:44 +00:00
|
|
|
optional_recursive_mutex listLock;
|
2012-12-29 01:10:29 +00:00
|
|
|
|
2013-02-03 23:41:16 +00:00
|
|
|
bool interruptRunning;
|
2015-07-26 20:38:40 +00:00
|
|
|
GPURunState gpuState;
|
2013-04-04 07:35:38 +00:00
|
|
|
bool isbreak;
|
2013-04-07 19:45:42 +00:00
|
|
|
u64 drawCompleteTicks;
|
2013-04-09 07:56:04 +00:00
|
|
|
u64 busyTicks;
|
2012-12-29 01:10:29 +00:00
|
|
|
|
2013-04-28 21:23:30 +00:00
|
|
|
int downcount;
|
2013-04-03 15:10:35 +00:00
|
|
|
u64 startingTicks;
|
|
|
|
u32 cycleLastPC;
|
|
|
|
int cyclesExecuted;
|
|
|
|
|
2012-12-29 01:10:29 +00:00
|
|
|
bool dumpNextFrame_;
|
|
|
|
bool dumpThisFrame_;
|
2013-04-01 06:02:46 +00:00
|
|
|
bool interruptsEnabled_;
|
2016-12-21 17:13:58 +00:00
|
|
|
bool resized_;
|
2017-01-28 10:39:34 +00:00
|
|
|
DrawType lastDraw_;
|
2013-02-03 23:41:16 +00:00
|
|
|
|
2013-08-14 04:42:48 +00:00
|
|
|
private:
|
2016-12-21 17:33:08 +00:00
|
|
|
|
2013-08-11 20:41:42 +00:00
|
|
|
// For CPU/GPU sync.
|
2016-10-12 09:13:16 +00:00
|
|
|
#ifdef __ANDROID__
|
2016-12-05 15:51:28 +00:00
|
|
|
alignas(16) std::atomic<u64> curTickEst_;
|
2013-08-12 15:51:19 +00:00
|
|
|
#else
|
2013-08-12 15:40:36 +00:00
|
|
|
volatile MEMORY_ALIGNED16(u64) curTickEst_;
|
2013-08-11 20:41:42 +00:00
|
|
|
recursive_mutex curTickEstLock_;
|
2013-08-12 15:51:19 +00:00
|
|
|
#endif
|
2013-08-11 20:41:42 +00:00
|
|
|
|
2013-08-14 04:42:48 +00:00
|
|
|
inline void UpdateTickEstimate(u64 value) {
|
2016-10-12 09:13:16 +00:00
|
|
|
#if defined(_M_X64) || defined(__ANDROID__)
|
2013-08-12 15:40:36 +00:00
|
|
|
curTickEst_ = value;
|
|
|
|
#elif defined(_M_SSE)
|
|
|
|
__m64 result = *(__m64 *)&value;
|
|
|
|
*(__m64 *)&curTickEst_ = result;
|
2013-08-13 08:01:40 +00:00
|
|
|
_mm_empty();
|
2013-08-12 15:40:36 +00:00
|
|
|
#else
|
2013-08-11 20:41:42 +00:00
|
|
|
lock_guard guard(curTickEstLock_);
|
|
|
|
curTickEst_ = value;
|
2013-08-12 15:40:36 +00:00
|
|
|
#endif
|
2013-08-11 20:41:42 +00:00
|
|
|
}
|
|
|
|
|
2014-06-14 15:42:18 +00:00
|
|
|
// Debug stats.
|
|
|
|
double timeSteppingStarted_;
|
|
|
|
double timeSpentStepping_;
|
2013-02-03 23:41:16 +00:00
|
|
|
};
|