1 #pragma once 2 3 #include "ppsspp_config.h" 4 #include "Common/Common.h" 5 #include "Common/MemoryUtil.h" 6 #include "GPU/GPUInterface.h" 7 #include "GPU/GPUState.h" 8 #include "GPU/Common/GPUDebugInterface.h" 9 10 #if defined(__ANDROID__) 11 #include <atomic> 12 #endif 13 14 #if defined(_M_SSE) 15 #include <emmintrin.h> 16 #endif 17 18 class FramebufferManagerCommon; 19 class TextureCacheCommon; 20 class DrawEngineCommon; 21 class GraphicsContext; 22 namespace Draw { 23 class DrawContext; 24 } 25 26 enum DrawType { 27 DRAW_UNKNOWN, 28 DRAW_PRIM, 29 DRAW_SPLINE, 30 DRAW_BEZIER, 31 }; 32 33 enum { 34 FLAG_FLUSHBEFORE = 1, 35 FLAG_FLUSHBEFOREONCHANGE = 2, 36 FLAG_EXECUTE = 4, 37 FLAG_EXECUTEONCHANGE = 8, 38 FLAG_READS_PC = 16, 39 FLAG_WRITES_PC = 32, 40 FLAG_DIRTYONCHANGE = 64, // NOTE: Either this or FLAG_EXECUTE*, not both! 41 }; 42 43 struct TransformedVertex { 44 union { 45 struct { 46 float x, y, z, fog; // in case of morph, preblend during decode 47 }; 48 float pos[4]; 49 }; 50 union { 51 struct { 52 float u; float v; float w; // scaled by uscale, vscale, if there 53 }; 54 float uv[3]; 55 }; 56 union { 57 u8 color0[4]; // prelit 58 u32 color0_32; 59 }; 60 union { 61 u8 color1[4]; // prelit 62 u32 color1_32; 63 }; 64 }; 65 66 class GPUCommon : public GPUInterface, public GPUDebugInterface { 67 public: 68 GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw); 69 virtual ~GPUCommon(); 70 GetDrawContext()71 Draw::DrawContext *GetDrawContext() override { 72 return draw_; 73 } 74 virtual void CheckGPUFeatures() = 0; 75 76 void UpdateCmdInfo(); 77 IsReady()78 bool IsReady() override { 79 return true; 80 } CancelReady()81 void CancelReady() override { 82 } 83 void Reinitialize() override; 84 85 void BeginHostFrame() override; 86 void EndHostFrame() override; 87 88 void InterruptStart(int listid) override; 89 void InterruptEnd(int listid) override; 90 void SyncEnd(GPUSyncType waitType, int listid, bool wokeThreads) override; EnableInterrupts(bool enable)91 void EnableInterrupts(bool enable) override { 92 interruptsEnabled_ = enable; 93 } 94 95 void Resized() override; 96 void DumpNextFrame() override; 97 98 void ExecuteOp(u32 op, u32 diff) override; 99 void PreExecuteOp(u32 op, u32 diff) override; 100 101 bool InterpretList(DisplayList &list) override; 102 void ProcessDLQueue(); 103 u32 UpdateStall(int listid, u32 newstall) override; 104 u32 EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer<PspGeListArgs> args, bool head) override; 105 u32 DequeueList(int listid) override; 106 int ListSync(int listid, int mode) override; 107 u32 DrawSync(int mode) override; 108 int GetStack(int index, u32 stackPtr) override; 109 void DoState(PointerWrap &p) override; 110 bool BusyDrawing() override; 111 u32 Continue() override; 112 u32 Break(int mode) override; 113 void ReapplyGfxState() override; 114 115 void CopyDisplayToOutput(bool reallyDirty) override = 0; 116 void InitClear() override = 0; 117 bool PerformMemoryCopy(u32 dest, u32 src, int size) override; 118 bool PerformMemorySet(u32 dest, u8 v, int size) override; 119 bool PerformMemoryDownload(u32 dest, int size) override; 120 bool PerformMemoryUpload(u32 dest, int size) override; 121 122 void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override; 123 void NotifyVideoUpload(u32 addr, int size, int width, int format) override; 124 bool PerformStencilUpload(u32 dest, int size) override; 125 126 void Execute_OffsetAddr(u32 op, u32 diff); 127 void Execute_Vaddr(u32 op, u32 diff); 128 void Execute_Iaddr(u32 op, u32 diff); 129 void Execute_Origin(u32 op, u32 diff); 130 void Execute_Jump(u32 op, u32 diff); 131 void Execute_JumpFast(u32 op, u32 diff); 132 void Execute_BJump(u32 op, u32 diff); 133 void Execute_Call(u32 op, u32 diff); 134 void Execute_CallFast(u32 op, u32 diff); 135 void Execute_Ret(u32 op, u32 diff); 136 void Execute_End(u32 op, u32 diff); 137 138 void Execute_VertexType(u32 op, u32 diff); 139 void Execute_VertexTypeSkinning(u32 op, u32 diff); 140 141 void Execute_Prim(u32 op, u32 diff); 142 void Execute_Bezier(u32 op, u32 diff); 143 void Execute_Spline(u32 op, u32 diff); 144 void Execute_BoundingBox(u32 op, u32 diff); 145 void Execute_BlockTransferStart(u32 op, u32 diff); 146 147 void Execute_LoadClut(u32 op, u32 diff); 148 149 void Execute_TexSize0(u32 op, u32 diff); 150 void Execute_TexLevel(u32 op, u32 diff); 151 152 void Execute_WorldMtxNum(u32 op, u32 diff); 153 void Execute_WorldMtxData(u32 op, u32 diff); 154 void Execute_ViewMtxNum(u32 op, u32 diff); 155 void Execute_ViewMtxData(u32 op, u32 diff); 156 void Execute_ProjMtxNum(u32 op, u32 diff); 157 void Execute_ProjMtxData(u32 op, u32 diff); 158 void Execute_TgenMtxNum(u32 op, u32 diff); 159 void Execute_TgenMtxData(u32 op, u32 diff); 160 void Execute_BoneMtxNum(u32 op, u32 diff); 161 void Execute_BoneMtxData(u32 op, u32 diff); 162 163 void Execute_MorphWeight(u32 op, u32 diff); 164 165 void Execute_ImmVertexAlphaPrim(u32 op, u32 diff); 166 167 void Execute_Unknown(u32 op, u32 diff); 168 169 int EstimatePerVertexCost(); 170 171 // Note: Not virtual! 172 void Flush(); 173 174 #ifdef USE_CRT_DBG 175 #undef new 176 #endif new(size_t s)177 void *operator new(size_t s) { 178 return AllocateAlignedMemory(s, 16); 179 } delete(void * p)180 void operator delete(void *p) { 181 FreeAlignedMemory(p); 182 } 183 #ifdef USE_CRT_DBG 184 #define new DBG_NEW 185 #endif 186 187 // From GPUDebugInterface. 188 bool GetCurrentDisplayList(DisplayList &list) override; 189 bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) override; 190 bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer) override; 191 bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) override; 192 bool GetCurrentTexture(GPUDebugBuffer &buffer, int level) override; 193 bool GetCurrentClut(GPUDebugBuffer &buffer) override; 194 bool GetCurrentSimpleVertices(int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices) override; 195 bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override; 196 DebugGetShaderIDs(DebugShaderType shader)197 std::vector<std::string> DebugGetShaderIDs(DebugShaderType shader) override { return std::vector<std::string>(); }; DebugGetShaderString(std::string id,DebugShaderType shader,DebugShaderStringType stringType)198 std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override { 199 return "N/A"; 200 } 201 bool DescribeCodePtr(const u8 *ptr, std::string &name) override; 202 203 std::vector<DisplayList> ActiveDisplayLists() override; 204 void ResetListPC(int listID, u32 pc) override; 205 void ResetListStall(int listID, u32 stall) override; 206 void ResetListState(int listID, DisplayListState state) override; 207 208 GPUDebugOp DissassembleOp(u32 pc, u32 op) override; 209 std::vector<GPUDebugOp> DissassembleOpRange(u32 startpc, u32 endpc) override; 210 211 void NotifySteppingEnter() override; 212 void NotifySteppingExit() override; 213 214 u32 GetRelativeAddress(u32 data) override; 215 u32 GetVertexAddress() override; 216 u32 GetIndexAddress() override; 217 GPUgstate GetGState() override; 218 void SetCmdValue(u32 op) override; 219 UpdateUVScaleOffset()220 void UpdateUVScaleOffset() { 221 #ifdef _M_SSE 222 __m128i values = _mm_slli_epi32(_mm_load_si128((const __m128i *)&gstate.texscaleu), 8); 223 _mm_storeu_si128((__m128i *)&gstate_c.uv, values); 224 #elif PPSSPP_PLATFORM(ARM_NEON) 225 const uint32x4_t values = vshlq_n_u32(vld1q_u32(&gstate.texscaleu), 8); 226 vst1q_u32(&gstate_c.uv, values); 227 #else 228 gstate_c.uv.uScale = getFloat24(gstate.texscaleu); 229 gstate_c.uv.vScale = getFloat24(gstate.texscalev); 230 gstate_c.uv.uOff = getFloat24(gstate.texoffsetu); 231 gstate_c.uv.vOff = getFloat24(gstate.texoffsetv); 232 #endif 233 } 234 getList(int listid)235 DisplayList* getList(int listid) override { 236 return &dls[listid]; 237 } 238 GetDisplayLists()239 const std::list<int>& GetDisplayLists() override { 240 return dlQueue; 241 } 242 std::vector<FramebufferInfo> GetFramebufferList() override; ClearShaderCache()243 void ClearShaderCache() override {} CleanupBeforeUI()244 void CleanupBeforeUI() override {} 245 GetListTicks(int listid)246 s64 GetListTicks(int listid) override { 247 if (listid >= 0 && listid < DisplayListMaxCount) { 248 return dls[listid].waitTicks; 249 } 250 return -1; 251 } 252 253 bool FramebufferDirty() override; 254 bool FramebufferReallyDirty() override; 255 256 typedef void (GPUCommon::*CmdFunc)(u32 op, u32 diff); 257 GetReportingInfo(std::string & primaryInfo,std::string & fullInfo)258 void GetReportingInfo(std::string &primaryInfo, std::string &fullInfo) override { 259 primaryInfo = reportingPrimaryInfo_; 260 fullInfo = reportingFullInfo_; 261 } 262 263 protected: 264 void DeviceLost() override; 265 void DeviceRestore() override; 266 SetDrawType(DrawType type,GEPrimitiveType prim)267 void SetDrawType(DrawType type, GEPrimitiveType prim) { 268 if (type != lastDraw_) { 269 // We always flush when drawing splines/beziers so no need to do so here 270 gstate_c.Dirty(DIRTY_UVSCALEOFFSET | DIRTY_VERTEXSHADER_STATE); 271 lastDraw_ = type; 272 } 273 // Prim == RECTANGLES can cause CanUseHardwareTransform to flip, so we need to dirty. 274 // Also, culling may be affected so dirty the raster state. 275 if ((prim == GE_PRIM_RECTANGLES) != (lastPrim_ == GE_PRIM_RECTANGLES)) { 276 Flush(); 277 gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE); 278 lastPrim_ = prim; 279 } 280 } 281 282 void BeginFrame() override; 283 void UpdateVsyncInterval(bool force); 284 285 virtual void FastRunLoop(DisplayList &list); 286 287 void SlowRunLoop(DisplayList &list); 288 void UpdatePC(u32 currentPC, u32 newPC); 289 void UpdateState(GPURunState state); 290 void PopDLQueue(); 291 void CheckDrawSync(); 292 int GetNextListIndex(); 293 virtual void FastLoadBoneMatrix(u32 target); 294 295 // TODO: Unify this. FinishDeferred()296 virtual void FinishDeferred() {} 297 298 void DoBlockTransfer(u32 skipDrawReason); 299 void DoExecuteCall(u32 target); 300 AdvanceVerts(u32 vertType,int count,int bytesRead)301 void AdvanceVerts(u32 vertType, int count, int bytesRead) { 302 if ((vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { 303 int indexShift = ((vertType & GE_VTYPE_IDX_MASK) >> GE_VTYPE_IDX_SHIFT) - 1; 304 gstate_c.indexAddr += count << indexShift; 305 } else { 306 gstate_c.vertexAddr += bytesRead; 307 } 308 } 309 310 size_t FormatGPUStatsCommon(char *buf, size_t size); 311 312 FramebufferManagerCommon *framebufferManager_ = nullptr; 313 TextureCacheCommon *textureCache_ = nullptr; 314 DrawEngineCommon *drawEngineCommon_ = nullptr; 315 ShaderManagerCommon *shaderManager_ = nullptr; 316 317 GraphicsContext *gfxCtx_; 318 Draw::DrawContext *draw_; 319 320 struct CommandInfo { 321 uint64_t flags; 322 GPUCommon::CmdFunc func; 323 }; 324 325 static CommandInfo cmdInfo_[256]; 326 327 typedef std::list<int> DisplayListQueue; 328 329 int nextListID; 330 DisplayList dls[DisplayListMaxCount]; 331 DisplayList *currentList; 332 DisplayListQueue dlQueue; 333 334 bool interruptRunning = false; 335 GPURunState gpuState = GPUSTATE_RUNNING; 336 bool isbreak; 337 u64 drawCompleteTicks; 338 u64 busyTicks; 339 340 int downcount; 341 u64 startingTicks; 342 u32 cycleLastPC; 343 int cyclesExecuted; 344 345 bool dumpNextFrame_ = false; 346 bool dumpThisFrame_ = false; 347 bool debugRecording_; 348 bool interruptsEnabled_; 349 bool resized_ = false; 350 DrawType lastDraw_ = DRAW_UNKNOWN; 351 GEPrimitiveType lastPrim_ = GE_PRIM_INVALID; 352 353 int vertexCost_ = 0; 354 355 // No idea how big this buffer needs to be. 356 enum { 357 MAX_IMMBUFFER_SIZE = 32, 358 }; 359 360 TransformedVertex immBuffer_[MAX_IMMBUFFER_SIZE]; 361 int immCount_ = 0; 362 GEPrimitiveType immPrim_; 363 364 std::string reportingPrimaryInfo_; 365 std::string reportingFullInfo_; 366 367 private: 368 void FlushImm(); 369 // Debug stats. 370 double timeSteppingStarted_; 371 double timeSpentStepping_; 372 int lastVsync_ = -1; 373 }; 374 375 struct CommonCommandTableEntry { 376 uint8_t cmd; 377 uint8_t flags; 378 uint64_t dirty; 379 GPUCommon::CmdFunc func; 380 }; 381 382 extern const CommonCommandTableEntry commonCommandTable[]; 383 extern size_t commonCommandTableSize; 384