diff --git a/GPU/Common/FramebufferCommon.h b/GPU/Common/FramebufferCommon.h index c3c5069dfa..97fd9204cb 100644 --- a/GPU/Common/FramebufferCommon.h +++ b/GPU/Common/FramebufferCommon.h @@ -236,6 +236,8 @@ public: void SetRenderSize(VirtualFramebuffer *vfb); void SetSafeSize(u16 w, u16 h); + virtual void Resized() = 0; + protected: void UpdateSize(); diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 4e88b8d68c..e32c391a64 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -63,10 +63,6 @@ TextureCacheCommon::~TextureCacheCommon() { FreeAlignedMemory(clutBufRaw_); } -bool TextureCacheCommon::SetOffsetTexture(u32 offset) { - return false; -} - int TextureCacheCommon::AttachedDrawingHeight() { if (nextTexture_) { if (nextTexture_->framebuffer) { diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 462296d34b..4c2be709d6 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -50,7 +50,9 @@ public: void LoadClut(u32 clutAddr, u32 loadBytes); bool GetCurrentClutBuffer(GPUDebugBuffer &buffer); - virtual bool SetOffsetTexture(u32 offset); + virtual bool SetOffsetTexture(u32 offset) = 0; + virtual void Invalidate(u32 addr, int size, GPUInvalidationType type) = 0; + virtual void InvalidateAll(GPUInvalidationType type) = 0; // FramebufferManager keeps TextureCache updated about what regions of memory are being rendered to. void NotifyFramebuffer(u32 address, VirtualFramebuffer *framebuffer, FramebufferNotification msg); diff --git a/GPU/Directx9/FramebufferDX9.h b/GPU/Directx9/FramebufferDX9.h index f11bb5d3ee..e3b6cb844e 100644 --- a/GPU/Directx9/FramebufferDX9.h +++ b/GPU/Directx9/FramebufferDX9.h @@ -63,7 +63,7 @@ public: void DestroyAllFBOs(bool forceDelete); void EndFrame(); - void Resized(); + void Resized() override; void DeviceLost(); void CopyDisplayToOutput(); void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old); diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index cf9e91f0a7..cbec9370e3 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -394,21 +394,26 @@ static const CommandTableEntry commandTable[] = { GPU_DX9::CommandInfo GPU_DX9::cmdInfo_[256]; GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx) -: resized_(false), gfxCtx_(gfxCtx) { +: gfxCtx_(gfxCtx) { lastVsync_ = g_Config.bVSync ? 1 : 0; dxstate.SetVSyncInterval(g_Config.bVSync); + framebufferManagerDX9_ = new FramebufferManagerDX9(); + framebufferManager_ = framebufferManagerDX9_; + textureCacheDX9_ = new TextureCacheDX9(); + textureCache_ = textureCacheDX9_; + shaderManager_ = new ShaderManagerDX9(); drawEngine_.SetShaderManager(shaderManager_); - drawEngine_.SetTextureCache(&textureCache_); - drawEngine_.SetFramebufferManager(&framebufferManager_); - framebufferManager_.Init(); - framebufferManager_.SetTextureCache(&textureCache_); - framebufferManager_.SetShaderManager(shaderManager_); - framebufferManager_.SetTransformDrawEngine(&drawEngine_); - textureCache_.SetFramebufferManager(&framebufferManager_); - textureCache_.SetDepalShaderCache(&depalShaderCache_); - textureCache_.SetShaderManager(shaderManager_); + drawEngine_.SetTextureCache(textureCacheDX9_); + drawEngine_.SetFramebufferManager(framebufferManagerDX9_); + framebufferManagerDX9_->Init(); + framebufferManagerDX9_->SetTextureCache(textureCacheDX9_); + framebufferManagerDX9_->SetShaderManager(shaderManager_); + framebufferManagerDX9_->SetTransformDrawEngine(&drawEngine_); + textureCacheDX9_->SetFramebufferManager(framebufferManagerDX9_); + textureCacheDX9_->SetDepalShaderCache(&depalShaderCache_); + textureCacheDX9_->SetShaderManager(shaderManager_); // Sanity check gstate if ((int *)&gstate.transferstart - (int *)&gstate != 0xEA) { @@ -447,7 +452,7 @@ GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx) // Some of our defaults are different from hw defaults, let's assert them. // We restore each frame anyway, but here is convenient for tests. dxstate.Restore(); - textureCache_.NotifyConfigChanged(); + textureCache_->NotifyConfigChanged(); } void GPU_DX9::UpdateCmdInfo() { @@ -500,7 +505,7 @@ void GPU_DX9::CheckGPUFeatures() { } GPU_DX9::~GPU_DX9() { - framebufferManager_.DestroyAllFBOs(true); + framebufferManagerDX9_->DestroyAllFBOs(true); shaderManager_->ClearCache(true); delete shaderManager_; } @@ -519,18 +524,14 @@ void GPU_DX9::DeviceLost() { // Simply drop all caches and textures. // FBOs appear to survive? Or no? shaderManager_->ClearCache(false); - textureCache_.Clear(false); - framebufferManager_.DeviceLost(); + textureCacheDX9_->Clear(false); + framebufferManagerDX9_->DeviceLost(); } void GPU_DX9::DeviceRestore() { // Nothing needed. } -void GPU_DX9::InitClear() { - ScheduleEvent(GPU_EVENT_INIT_CLEAR); -} - void GPU_DX9::InitClearInternal() { bool useNonBufferedRendering = g_Config.iRenderingMode == FB_NON_BUFFERED_MODE; if (useNonBufferedRendering) { @@ -557,7 +558,7 @@ void GPU_DX9::BeginFrameInternal() { if (resized_) { UpdateCmdInfo(); drawEngine_.Resized(); - textureCache_.NotifyConfigChanged(); + textureCacheDX9_->NotifyConfigChanged(); resized_ = false; } @@ -570,7 +571,7 @@ void GPU_DX9::BeginFrameInternal() { lastVsync_ = desiredVSyncInterval; } - textureCache_.StartFrame(); + textureCacheDX9_->StartFrame(); drawEngine_.DecimateTrackedVertexArrays(); depalShaderCache_.Decimate(); // fragmentTestCache_.Decimate(); @@ -584,12 +585,12 @@ void GPU_DX9::BeginFrameInternal() { } shaderManager_->DirtyShader(); - framebufferManager_.BeginFrame(); + framebufferManagerDX9_->BeginFrame(); } void GPU_DX9::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) { host->GPUNotifyDisplay(framebuf, stride, format); - framebufferManager_.SetDisplayFramebuffer(framebuf, stride, format); + framebufferManagerDX9_->SetDisplayFramebuffer(framebuf, stride, format); } bool GPU_DX9::FramebufferDirty() { @@ -600,7 +601,7 @@ bool GPU_DX9::FramebufferDirty() { // Allow it to process fully before deciding if it's dirty. SyncThread(); } - VirtualFramebuffer *vfb = framebufferManager_.GetDisplayVFB(); + VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB(); if (vfb) { bool dirty = vfb->dirtyAfterDisplay; vfb->dirtyAfterDisplay = false; @@ -617,7 +618,7 @@ bool GPU_DX9::FramebufferReallyDirty() { SyncThread(); } - VirtualFramebuffer *vfb = framebufferManager_.GetDisplayVFB(); + VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB(); if (vfb) { bool dirty = vfb->reallyDirtyAfterDisplay; vfb->reallyDirtyAfterDisplay = false; @@ -626,18 +627,14 @@ bool GPU_DX9::FramebufferReallyDirty() { return true; } -void GPU_DX9::CopyDisplayToOutput() { - ScheduleEvent(GPU_EVENT_COPY_DISPLAY_TO_OUTPUT); -} - void GPU_DX9::CopyDisplayToOutputInternal() { dxstate.depthWrite.set(true); dxstate.colorMask.set(true, true, true, true); drawEngine_.Flush(); - framebufferManager_.CopyDisplayToOutput(); - framebufferManager_.EndFrame(); + framebufferManagerDX9_->CopyDisplayToOutput(); + framebufferManagerDX9_->EndFrame(); // shaderManager_->EndFrame(); shaderManager_->DirtyLastShader(); @@ -673,41 +670,6 @@ void GPU_DX9::FinishDeferred() { drawEngine_.FinishDeferred(); } -void GPU_DX9::ProcessEvent(GPUEvent ev) { - switch (ev.type) { - 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; - - default: - GPUCommon::ProcessEvent(ev); - } -} - inline void GPU_DX9::CheckFlushOp(int cmd, u32 diff) { const u8 cmdFlags = cmdInfo_[cmd].flags; if ((cmdFlags & FLAG_FLUSHBEFORE) || (diff && (cmdFlags & FLAG_FLUSHBEFOREONCHANGE))) { @@ -787,7 +749,7 @@ void GPU_DX9::Execute_Prim(u32 op, u32 diff) { } // This also make skipping drawing very effective. - framebufferManager_.SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason); + framebufferManagerDX9_->SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason); if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) { drawEngine_.SetupVertexDecoder(gstate.vertType); // Rough estimate, not sure what's correct. @@ -835,7 +797,7 @@ void GPU_DX9::Execute_Prim(u32 op, u32 diff) { void GPU_DX9::Execute_Bezier(u32 op, u32 diff) { // This also make skipping drawing very effective. - framebufferManager_.SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason); + framebufferManagerDX9_->SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason); if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) { // TODO: Should this eat some cycles? Probably yes. Not sure if important. return; @@ -878,7 +840,7 @@ void GPU_DX9::Execute_Bezier(u32 op, u32 diff) { void GPU_DX9::Execute_Spline(u32 op, u32 diff) { // This also make skipping drawing very effective. - framebufferManager_.SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason); + framebufferManagerDX9_->SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason); if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) { // TODO: Should this eat some cycles? Probably yes. Not sure if important. return; @@ -1060,7 +1022,7 @@ void GPU_DX9::Execute_TexLevel(u32 op, u32 diff) { void GPU_DX9::Execute_LoadClut(u32 op, u32 diff) { gstate_c.textureChanged |= TEXCHANGE_PARAMSONLY; - textureCache_.LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes()); + textureCacheDX9_->LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes()); // This could be used to "dirty" textures with clut. } @@ -1876,8 +1838,8 @@ void GPU_DX9::GetStats(char *buffer, size_t bufsize) { gpuStats.numVertsSubmitted, gpuStats.numCachedVertsDrawn, gpuStats.numUncachedVertsDrawn, - (int)framebufferManager_.NumVFBs(), - (int)textureCache_.NumLoadedTextures(), + (int)framebufferManagerDX9_->NumVFBs(), + (int)textureCacheDX9_->NumLoadedTextures(), gpuStats.numTexturesDecoded, gpuStats.numTextureInvalidations, shaderManager_->NumVertexShaders(), @@ -1885,231 +1847,8 @@ void GPU_DX9::GetStats(char *buffer, size_t bufsize) { ); } -void GPU_DX9::DoBlockTransfer(u32 skipDrawReason) { - // TODO: This is used a lot to copy data around between render targets and textures, - // and also to quickly load textures from RAM to VRAM. So we should do checks like the following: - // * Does dstBasePtr point to an existing texture? If so maybe reload it immediately. - // - // * Does srcBasePtr point to a render target, and dstBasePtr to a texture? If so - // either copy between rt and texture or reassign the texture to point to the render target - // - // etc.... - - u32 srcBasePtr = gstate.getTransferSrcAddress(); - u32 srcStride = gstate.getTransferSrcStride(); - - u32 dstBasePtr = gstate.getTransferDstAddress(); - u32 dstStride = gstate.getTransferDstStride(); - - int srcX = gstate.getTransferSrcX(); - int srcY = gstate.getTransferSrcY(); - - int dstX = gstate.getTransferDstX(); - int dstY = gstate.getTransferDstY(); - - int width = gstate.getTransferWidth(); - int height = gstate.getTransferHeight(); - - int bpp = gstate.getTransferBpp(); - - DEBUG_LOG(G3D, "Block transfer: %08x/%x -> %08x/%x, %ix%ix%i (%i,%i)->(%i,%i)", srcBasePtr, srcStride, dstBasePtr, dstStride, width, height, bpp, srcX, srcY, dstX, dstY); - - if (!Memory::IsValidAddress(srcBasePtr)) { - ERROR_LOG_REPORT(G3D, "BlockTransfer: Bad source transfer address %08x!", srcBasePtr); - return; - } - - if (!Memory::IsValidAddress(dstBasePtr)) { - ERROR_LOG_REPORT(G3D, "BlockTransfer: Bad destination transfer address %08x!", dstBasePtr); - return; - } - - // Check that the last address of both source and dest are valid addresses - - u32 srcLastAddr = srcBasePtr + ((height - 1 + srcY) * srcStride + (srcX + width - 1)) * bpp; - u32 dstLastAddr = dstBasePtr + ((height - 1 + dstY) * dstStride + (dstX + width - 1)) * bpp; - - if (!Memory::IsValidAddress(srcLastAddr)) { - ERROR_LOG_REPORT(G3D, "Bottom-right corner of source of block transfer is at an invalid address: %08x", srcLastAddr); - return; - } - if (!Memory::IsValidAddress(dstLastAddr)) { - ERROR_LOG_REPORT(G3D, "Bottom-right corner of destination of block transfer is at an invalid address: %08x", srcLastAddr); - return; - } - - // Tell the framebuffer manager to take action if possible. If it does the entire thing, let's just return. - if (!framebufferManager_.NotifyBlockTransferBefore(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason)) { - // Do the copy! (Hm, if we detect a drawn video frame (see below) then we could maybe skip this?) - // Can use GetPointerUnchecked because we checked the addresses above. We could also avoid them - // entirely by walking a couple of pointers... - if (srcStride == dstStride && (u32)width == srcStride) { - // Common case in God of War, let's do it all in one chunk. - u32 srcLineStartAddr = srcBasePtr + (srcY * srcStride + srcX) * bpp; - u32 dstLineStartAddr = dstBasePtr + (dstY * dstStride + dstX) * bpp; - const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr); - u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr); - memcpy(dst, src, width * height * bpp); - } else { - for (int y = 0; y < height; y++) { - u32 srcLineStartAddr = srcBasePtr + ((y + srcY) * srcStride + srcX) * bpp; - u32 dstLineStartAddr = dstBasePtr + ((y + dstY) * dstStride + dstX) * bpp; - - const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr); - u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr); - memcpy(dst, src, width * bpp); - } - } - - textureCache_.Invalidate(dstBasePtr + (dstY * dstStride + dstX) * bpp, height * dstStride * bpp, GPU_INVALIDATE_HINT); - framebufferManager_.NotifyBlockTransferAfter(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason); - } - - CBreakPoints::ExecMemCheck(srcBasePtr + (srcY * srcStride + srcX) * bpp, false, height * srcStride * bpp, currentMIPS->pc); - CBreakPoints::ExecMemCheck(dstBasePtr + (srcY * dstStride + srcX) * bpp, true, height * dstStride * bpp, currentMIPS->pc); - - // TODO: Correct timing appears to be 1.9, but erring a bit low since some of our other timing is inaccurate. - cyclesExecuted += ((height * width * bpp) * 16) / 10; -} - -void GPU_DX9::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 GPU_DX9::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type) { - if (size > 0) - textureCache_.Invalidate(addr, size, type); - else - textureCache_.InvalidateAll(type); - - if (type != GPU_INVALIDATE_ALL && framebufferManager_.MayIntersectFramebuffer(addr)) { - // If we're doing block transfers, we shouldn't need this, and it'll only confuse us. - // Vempire invalidates (with writeback) after drawing, but before blitting. - if (!g_Config.bBlockTransferGPU || type == GPU_INVALIDATE_SAFE) { - framebufferManager_.UpdateFromMemory(addr, size, type == GPU_INVALIDATE_SAFE); - } - } -} - -void GPU_DX9::NotifyVideoUpload(u32 addr, int size, int width, int format) { - if (Memory::IsVRAMAddress(addr)) { - framebufferManager_.NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); - } - textureCache_.NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); - InvalidateCache(addr, size, GPU_INVALIDATE_SAFE); -} - -void GPU_DX9::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 GPU_DX9::PerformMemorySetInternal(u32 dest, u8 v, int size) { - if (!framebufferManager_.NotifyFramebufferCopy(dest, dest, size, true, gstate_c.skipDrawReason)) { - InvalidateCache(dest, size, GPU_INVALIDATE_HINT); - } -} - -void GPU_DX9::PerformStencilUploadInternal(u32 dest, int size) { - framebufferManager_.NotifyStencilUpload(dest, size); -} - -bool GPU_DX9::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); - } - return true; - } - - InvalidateCache(dest, size, GPU_INVALIDATE_HINT); - return false; -} - -bool GPU_DX9::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); - } - return true; - } - - // Or perhaps a texture, let's invalidate. - InvalidateCache(dest, size, GPU_INVALIDATE_HINT); - return false; -} - -bool GPU_DX9::PerformMemoryDownload(u32 dest, int size) { - // Cheat a bit to force a download of the framebuffer. - // VRAM + 0x00400000 is simply a VRAM mirror. - if (Memory::IsVRAMAddress(dest)) { - return PerformMemoryCopy(dest ^ 0x00400000, dest, size); - } - return false; -} - -bool GPU_DX9::PerformMemoryUpload(u32 dest, int size) { - // Cheat a bit to force an upload of the framebuffer. - // VRAM + 0x00400000 is simply a VRAM mirror. - if (Memory::IsVRAMAddress(dest)) { - return PerformMemoryCopy(dest, dest ^ 0x00400000, size); - } - return false; -} - -bool GPU_DX9::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); - } - return true; - } - return false; -} - void GPU_DX9::ClearCacheNextFrame() { - textureCache_.ClearNextFrame(); -} - -void GPU_DX9::Resized() { - resized_ = true; - framebufferManager_.Resized(); + textureCacheDX9_->ClearNextFrame(); } void GPU_DX9::ClearShaderCache() { @@ -2117,7 +1856,7 @@ void GPU_DX9::ClearShaderCache() { } std::vector GPU_DX9::GetFramebufferList() { - return framebufferManager_.GetFramebufferList(); + return framebufferManagerDX9_->GetFramebufferList(); } void GPU_DX9::DoState(PointerWrap &p) { @@ -2126,25 +1865,25 @@ void GPU_DX9::DoState(PointerWrap &p) { // TODO: Some of these things may not be necessary. // None of these are necessary when saving. if (p.mode == p.MODE_READ) { - textureCache_.Clear(true); + textureCacheDX9_->Clear(true); drawEngine_.ClearTrackedVertexArrays(); gstate_c.textureChanged = TEXCHANGE_UPDATED; - framebufferManager_.DestroyAllFBOs(true); + framebufferManagerDX9_->DestroyAllFBOs(true); shaderManager_->ClearCache(true); } } bool GPU_DX9::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) { - return framebufferManager_.GetCurrentFramebuffer(buffer, type, maxRes); + return framebufferManagerDX9_->GetCurrentFramebuffer(buffer, type, maxRes); } bool GPU_DX9::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) { - return framebufferManager_.GetCurrentDepthbuffer(buffer); + return framebufferManagerDX9_->GetCurrentDepthbuffer(buffer); } bool GPU_DX9::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) { - return framebufferManager_.GetCurrentStencilbuffer(buffer); + return framebufferManagerDX9_->GetCurrentStencilbuffer(buffer); } bool GPU_DX9::GetCurrentTexture(GPUDebugBuffer &buffer, int level) { @@ -2152,8 +1891,8 @@ bool GPU_DX9::GetCurrentTexture(GPUDebugBuffer &buffer, int level) { return false; } - textureCache_.SetTexture(true); - textureCache_.ApplyTexture(); + textureCacheDX9_->SetTexture(true); + textureCacheDX9_->ApplyTexture(); int w = gstate.getTextureWidth(level); int h = gstate.getTextureHeight(level); @@ -2237,7 +1976,7 @@ bool GPU_DX9::GetCurrentTexture(GPUDebugBuffer &buffer, int level) { } bool GPU_DX9::GetCurrentClut(GPUDebugBuffer &buffer) { - return textureCache_.GetCurrentClutBuffer(buffer); + return textureCacheDX9_->GetCurrentClutBuffer(buffer); } bool GPU_DX9::GetOutputFramebuffer(GPUDebugBuffer &buffer) { diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index ce0003a34e..a1bf7ac22a 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -37,23 +37,15 @@ class GPU_DX9 : public GPUCommon { public: GPU_DX9(GraphicsContext *gfxCtx); ~GPU_DX9(); + void CheckGPUFeatures(); - void InitClear() override; void PreExecuteOp(u32 op, u32 diff) override; void ExecuteOp(u32 op, u32 diff) override; void ReapplyGfxStateInternal() override; void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override; - void CopyDisplayToOutput() override; void BeginFrame() override; void GetStats(char *buffer, size_t bufsize) override; - void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override; - void NotifyVideoUpload(u32 addr, int size, int width, int format) override; - 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; - bool PerformStencilUpload(u32 dest, int size) override; void ClearCacheNextFrame() override; void DeviceLost() override; // Only happens on Android. Drop all textures and shaders. void DeviceRestore() override; @@ -61,11 +53,9 @@ public: void DumpNextFrame() override; void DoState(PointerWrap &p) override; - // Called by the window system if the window size changed. This will be reflected in PSPCoreParam.pixel*. - void Resized() override; void ClearShaderCache() override; bool DecodeTexture(u8 *dest, const GPUgstate &state) override { - return textureCache_.DecodeTexture(dest, state); + return textureCacheDX9_->DecodeTexture(dest, state); } bool FramebufferDirty() override; bool FramebufferReallyDirty() override; @@ -153,7 +143,6 @@ public: protected: void FastRunLoop(DisplayList &list) override; - void ProcessEvent(GPUEvent ev) override; void FastLoadBoneMatrix(u32 target) override; void FinishDeferred() override; @@ -163,27 +152,22 @@ private: void Flush() { drawEngine_.Flush(); } - void DoBlockTransfer(u32 skipDrawReason); - void ApplyDrawState(int prim); + // void ApplyDrawState(int prim); void CheckFlushOp(int cmd, u32 diff); void BuildReportingInfo(); - void InitClearInternal(); - void BeginFrameInternal(); - void CopyDisplayToOutputInternal(); - 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); - FramebufferManagerDX9 framebufferManager_; - TextureCacheDX9 textureCache_; + void InitClearInternal() override; + void BeginFrameInternal() override; + void CopyDisplayToOutputInternal() override; + + FramebufferManagerDX9 *framebufferManagerDX9_; + TextureCacheDX9 *textureCacheDX9_; DepalShaderCacheDX9 depalShaderCache_; DrawEngineDX9 drawEngine_; ShaderManagerDX9 *shaderManager_; static CommandInfo cmdInfo_[256]; - bool resized_; int lastVsync_; std::string reportingPrimaryInfo_; diff --git a/GPU/GLES/Framebuffer.h b/GPU/GLES/Framebuffer.h index ee80abbbf7..5ad05fc819 100644 --- a/GPU/GLES/Framebuffer.h +++ b/GPU/GLES/Framebuffer.h @@ -86,7 +86,7 @@ public: virtual void Init() override; void EndFrame(); - void Resized(); + void Resized() override; void DeviceLost(); void CopyDisplayToOutput(); void SetLineWidth(); diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 4b9ad6582b..5a1215a7bc 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -397,24 +397,29 @@ static const CommandTableEntry commandTable[] = { GPU_GLES::CommandInfo GPU_GLES::cmdInfo_[256]; GPU_GLES::GPU_GLES(GraphicsContext *ctx) -: resized_(false), gfxCtx_(ctx) { +: gfxCtx_(ctx) { UpdateVsyncInterval(true); CheckGPUFeatures(); shaderManager_ = new ShaderManager(); + framebufferManagerGL_ = new FramebufferManager(); + framebufferManager_ = framebufferManagerGL_; + textureCacheGL_ = new TextureCache(); + textureCache_ = textureCacheGL_; + drawEngine_.SetShaderManager(shaderManager_); - drawEngine_.SetTextureCache(&textureCache_); - drawEngine_.SetFramebufferManager(&framebufferManager_); + drawEngine_.SetTextureCache(textureCacheGL_); + drawEngine_.SetFramebufferManager(framebufferManagerGL_); drawEngine_.SetFragmentTestCache(&fragmentTestCache_); - framebufferManager_.Init(); - framebufferManager_.SetTextureCache(&textureCache_); - framebufferManager_.SetShaderManager(shaderManager_); - framebufferManager_.SetTransformDrawEngine(&drawEngine_); - textureCache_.SetFramebufferManager(&framebufferManager_); - textureCache_.SetDepalShaderCache(&depalShaderCache_); - textureCache_.SetShaderManager(shaderManager_); - textureCache_.SetTransformDrawEngine(&drawEngine_); - fragmentTestCache_.SetTextureCache(&textureCache_); + framebufferManagerGL_->Init(); + framebufferManagerGL_->SetTextureCache(textureCacheGL_); + framebufferManagerGL_->SetShaderManager(shaderManager_); + framebufferManagerGL_->SetTransformDrawEngine(&drawEngine_); + textureCacheGL_->SetFramebufferManager(framebufferManagerGL_); + textureCacheGL_->SetDepalShaderCache(&depalShaderCache_); + textureCacheGL_->SetShaderManager(shaderManager_); + textureCacheGL_->SetTransformDrawEngine(&drawEngine_); + fragmentTestCache_.SetTextureCache(textureCacheGL_); // Sanity check gstate if ((int *)&gstate.transferstart - (int *)&gstate != 0xEA) { @@ -457,7 +462,7 @@ GPU_GLES::GPU_GLES(GraphicsContext *ctx) // We restore each frame anyway, but here is convenient for tests. glstate.Restore(); drawEngine_.RestoreVAO(); - textureCache_.NotifyConfigChanged(); + textureCacheGL_->NotifyConfigChanged(); // Load shader cache. std::string discID = g_paramSFO.GetValueString("DISC_ID"); @@ -469,7 +474,7 @@ GPU_GLES::GPU_GLES(GraphicsContext *ctx) } GPU_GLES::~GPU_GLES() { - framebufferManager_.DestroyAllFBOs(true); + framebufferManagerGL_->DestroyAllFBOs(true); shaderManager_->ClearCache(true); depalShaderCache_.Clear(); fragmentTestCache_.Clear(); @@ -647,10 +652,10 @@ void GPU_GLES::DeviceLost() { // FBOs appear to survive? Or no? // TransformDraw has registered as a GfxResourceHolder. shaderManager_->ClearCache(false); - textureCache_.Clear(false); + textureCacheGL_->Clear(false); fragmentTestCache_.Clear(false); depalShaderCache_.Clear(); - framebufferManager_.DeviceLost(); + framebufferManagerGL_->DeviceLost(); } void GPU_GLES::DeviceRestore() { @@ -659,20 +664,11 @@ void GPU_GLES::DeviceRestore() { UpdateVsyncInterval(true); } -void GPU_GLES::InitClear() { - ScheduleEvent(GPU_EVENT_INIT_CLEAR); -} - -void GPU_GLES::Reinitialize() { - GPUCommon::Reinitialize(); - ScheduleEvent(GPU_EVENT_REINITIALIZE); -} - void GPU_GLES::ReinitializeInternal() { - textureCache_.Clear(true); + textureCacheGL_->Clear(true); depalShaderCache_.Clear(); - framebufferManager_.DestroyAllFBOs(true); - framebufferManager_.Resized(); + framebufferManagerGL_->DestroyAllFBOs(true); + framebufferManagerGL_->Resized(); } void GPU_GLES::InitClearInternal() { @@ -742,12 +738,12 @@ void GPU_GLES::BeginFrameInternal() { CheckGPUFeatures(); UpdateCmdInfo(); drawEngine_.Resized(); - textureCache_.NotifyConfigChanged(); + textureCacheGL_->NotifyConfigChanged(); } UpdateVsyncInterval(resized_); resized_ = false; - textureCache_.StartFrame(); + textureCacheGL_->StartFrame(); drawEngine_.DecimateTrackedVertexArrays(); drawEngine_.DecimateBuffers(); depalShaderCache_.Decimate(); @@ -771,12 +767,12 @@ void GPU_GLES::BeginFrameInternal() { // Not sure if this is really needed. shaderManager_->DirtyUniform(DIRTY_ALL); - framebufferManager_.BeginFrame(); + framebufferManagerGL_->BeginFrame(); } void GPU_GLES::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) { host->GPUNotifyDisplay(framebuf, stride, format); - framebufferManager_.SetDisplayFramebuffer(framebuf, stride, format); + framebufferManagerGL_->SetDisplayFramebuffer(framebuf, stride, format); } bool GPU_GLES::FramebufferDirty() { @@ -785,7 +781,7 @@ bool GPU_GLES::FramebufferDirty() { SyncThread(); } - VirtualFramebuffer *vfb = framebufferManager_.GetDisplayVFB(); + VirtualFramebuffer *vfb = framebufferManagerGL_->GetDisplayVFB(); if (vfb) { bool dirty = vfb->dirtyAfterDisplay; vfb->dirtyAfterDisplay = false; @@ -800,7 +796,7 @@ bool GPU_GLES::FramebufferReallyDirty() { SyncThread(); } - VirtualFramebuffer *vfb = framebufferManager_.GetDisplayVFB(); + VirtualFramebuffer *vfb = framebufferManagerGL_->GetDisplayVFB(); if (vfb) { bool dirty = vfb->reallyDirtyAfterDisplay; vfb->reallyDirtyAfterDisplay = false; @@ -809,13 +805,9 @@ bool GPU_GLES::FramebufferReallyDirty() { return true; } -void GPU_GLES::CopyDisplayToOutput() { - ScheduleEvent(GPU_EVENT_COPY_DISPLAY_TO_OUTPUT); -} - void GPU_GLES::CopyDisplayToOutputInternal() { // Flush anything left over. - framebufferManager_.RebindFramebuffer(); + framebufferManagerGL_->RebindFramebuffer(); drawEngine_.Flush(); shaderManager_->DirtyLastShader(); @@ -823,8 +815,8 @@ void GPU_GLES::CopyDisplayToOutputInternal() { glstate.depthWrite.set(GL_TRUE); glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - framebufferManager_.CopyDisplayToOutput(); - framebufferManager_.EndFrame(); + framebufferManagerGL_->CopyDisplayToOutput(); + framebufferManagerGL_->EndFrame(); // If buffered, discard the depth buffer of the backbuffer. Don't even know if we need one. #if 0 @@ -871,45 +863,6 @@ void GPU_GLES::FinishDeferred() { drawEngine_.FinishDeferred(); } -void GPU_GLES::ProcessEvent(GPUEvent ev) { - switch (ev.type) { - 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: - ReinitializeInternal(); - break; - - default: - GPUCommon::ProcessEvent(ev); - } -} - inline void GPU_GLES::CheckFlushOp(int cmd, u32 diff) { const u8 cmdFlags = cmdInfo_[cmd].flags; if ((cmdFlags & FLAG_FLUSHBEFORE) || (diff && (cmdFlags & FLAG_FLUSHBEFOREONCHANGE))) { @@ -965,7 +918,7 @@ void GPU_GLES::Execute_Prim(u32 op, u32 diff) { } // This also makes skipping drawing very effective. - framebufferManager_.SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason); + framebufferManagerGL_->SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason); if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) { drawEngine_.SetupVertexDecoder(gstate.vertType); // Rough estimate, not sure what's correct. @@ -1034,7 +987,7 @@ void GPU_GLES::Execute_VertexTypeSkinning(u32 op, u32 diff) { void GPU_GLES::Execute_Bezier(u32 op, u32 diff) { // This also make skipping drawing very effective. - framebufferManager_.SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason); + framebufferManagerGL_->SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason); if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) { // TODO: Should this eat some cycles? Probably yes. Not sure if important. return; @@ -1077,7 +1030,7 @@ void GPU_GLES::Execute_Bezier(u32 op, u32 diff) { void GPU_GLES::Execute_Spline(u32 op, u32 diff) { // This also make skipping drawing very effective. - framebufferManager_.SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason); + framebufferManagerGL_->SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason); if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) { // TODO: Should this eat some cycles? Probably yes. Not sure if important. return; @@ -1257,7 +1210,7 @@ void GPU_GLES::Execute_TexLevel(u32 op, u32 diff) { void GPU_GLES::Execute_LoadClut(u32 op, u32 diff) { gstate_c.textureChanged |= TEXCHANGE_PARAMSONLY; - textureCache_.LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes()); + textureCacheGL_->LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes()); // This could be used to "dirty" textures with clut. } @@ -2135,8 +2088,8 @@ void GPU_GLES::GetStats(char *buffer, size_t bufsize) { gpuStats.numVertsSubmitted, gpuStats.numCachedVertsDrawn, gpuStats.numUncachedVertsDrawn, - (int)framebufferManager_.NumVFBs(), - (int)textureCache_.NumLoadedTextures(), + (int)framebufferManagerGL_->NumVFBs(), + (int)textureCacheGL_->NumLoadedTextures(), gpuStats.numTexturesDecoded, gpuStats.numTextureInvalidations, shaderManager_->NumVertexShaders(), @@ -2144,233 +2097,8 @@ void GPU_GLES::GetStats(char *buffer, size_t bufsize) { shaderManager_->NumPrograms()); } -void GPU_GLES::DoBlockTransfer(u32 skipDrawReason) { - // TODO: This is used a lot to copy data around between render targets and textures, - // and also to quickly load textures from RAM to VRAM. So we should do checks like the following: - // * Does dstBasePtr point to an existing texture? If so maybe reload it immediately. - // - // * Does srcBasePtr point to a render target, and dstBasePtr to a texture? If so - // either copy between rt and texture or reassign the texture to point to the render target - // - // etc.... - - u32 srcBasePtr = gstate.getTransferSrcAddress(); - u32 srcStride = gstate.getTransferSrcStride(); - - u32 dstBasePtr = gstate.getTransferDstAddress(); - u32 dstStride = gstate.getTransferDstStride(); - - int srcX = gstate.getTransferSrcX(); - int srcY = gstate.getTransferSrcY(); - - int dstX = gstate.getTransferDstX(); - int dstY = gstate.getTransferDstY(); - - int width = gstate.getTransferWidth(); - int height = gstate.getTransferHeight(); - - int bpp = gstate.getTransferBpp(); - - DEBUG_LOG(G3D, "Block transfer: %08x/%x -> %08x/%x, %ix%ix%i (%i,%i)->(%i,%i)", srcBasePtr, srcStride, dstBasePtr, dstStride, width, height, bpp, srcX, srcY, dstX, dstY); - - if (!Memory::IsValidAddress(srcBasePtr)) { - ERROR_LOG_REPORT(G3D, "BlockTransfer: Bad source transfer address %08x!", srcBasePtr); - return; - } - - if (!Memory::IsValidAddress(dstBasePtr)) { - ERROR_LOG_REPORT(G3D, "BlockTransfer: Bad destination transfer address %08x!", dstBasePtr); - return; - } - - // Check that the last address of both source and dest are valid addresses - - u32 srcLastAddr = srcBasePtr + ((srcY + height - 1) * srcStride + (srcX + width - 1)) * bpp; - u32 dstLastAddr = dstBasePtr + ((dstY + height - 1) * dstStride + (dstX + width - 1)) * bpp; - - if (!Memory::IsValidAddress(srcLastAddr)) { - ERROR_LOG_REPORT(G3D, "Bottom-right corner of source of block transfer is at an invalid address: %08x", srcLastAddr); - return; - } - if (!Memory::IsValidAddress(dstLastAddr)) { - ERROR_LOG_REPORT(G3D, "Bottom-right corner of destination of block transfer is at an invalid address: %08x", srcLastAddr); - return; - } - - // Tell the framebuffer manager to take action if possible. If it does the entire thing, let's just return. - if (!framebufferManager_.NotifyBlockTransferBefore(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason)) { - // Do the copy! (Hm, if we detect a drawn video frame (see below) then we could maybe skip this?) - // Can use GetPointerUnchecked because we checked the addresses above. We could also avoid them - // entirely by walking a couple of pointers... - if (srcStride == dstStride && (u32)width == srcStride) { - // Common case in God of War, let's do it all in one chunk. - u32 srcLineStartAddr = srcBasePtr + (srcY * srcStride + srcX) * bpp; - u32 dstLineStartAddr = dstBasePtr + (dstY * dstStride + dstX) * bpp; - const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr); - u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr); - memcpy(dst, src, width * height * bpp); - } else { - for (int y = 0; y < height; y++) { - u32 srcLineStartAddr = srcBasePtr + ((y + srcY) * srcStride + srcX) * bpp; - u32 dstLineStartAddr = dstBasePtr + ((y + dstY) * dstStride + dstX) * bpp; - - const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr); - u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr); - memcpy(dst, src, width * bpp); - } - } - - textureCache_.Invalidate(dstBasePtr + (dstY * dstStride + dstX) * bpp, height * dstStride * bpp, GPU_INVALIDATE_HINT); - framebufferManager_.NotifyBlockTransferAfter(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason); - } - -#ifndef MOBILE_DEVICE - CBreakPoints::ExecMemCheck(srcBasePtr + (srcY * srcStride + srcX) * bpp, false, height * srcStride * bpp, currentMIPS->pc); - CBreakPoints::ExecMemCheck(dstBasePtr + (srcY * dstStride + srcX) * bpp, true, height * dstStride * bpp, currentMIPS->pc); -#endif - - // TODO: Correct timing appears to be 1.9, but erring a bit low since some of our other timing is inaccurate. - cyclesExecuted += ((height * width * bpp) * 16) / 10; -} - -void GPU_GLES::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 GPU_GLES::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type) { - if (size > 0) - textureCache_.Invalidate(addr, size, type); - else - textureCache_.InvalidateAll(type); - - if (type != GPU_INVALIDATE_ALL && framebufferManager_.MayIntersectFramebuffer(addr)) { - // If we're doing block transfers, we shouldn't need this, and it'll only confuse us. - // Vempire invalidates (with writeback) after drawing, but before blitting. - if (!g_Config.bBlockTransferGPU || type == GPU_INVALIDATE_SAFE) { - framebufferManager_.UpdateFromMemory(addr, size, type == GPU_INVALIDATE_SAFE); - } - } -} - -void GPU_GLES::NotifyVideoUpload(u32 addr, int size, int width, int format) { - if (Memory::IsVRAMAddress(addr)) { - framebufferManager_.NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); - } - textureCache_.NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); - InvalidateCache(addr, size, GPU_INVALIDATE_SAFE); -} - -void GPU_GLES::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 GPU_GLES::PerformMemorySetInternal(u32 dest, u8 v, int size) { - if (!framebufferManager_.NotifyFramebufferCopy(dest, dest, size, true, gstate_c.skipDrawReason)) { - InvalidateCache(dest, size, GPU_INVALIDATE_HINT); - } -} - -void GPU_GLES::PerformStencilUploadInternal(u32 dest, int size) { - framebufferManager_.NotifyStencilUpload(dest, size); -} - -bool GPU_GLES::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); - } - return true; - } - - InvalidateCache(dest, size, GPU_INVALIDATE_HINT); - return false; -} - -bool GPU_GLES::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); - } - return true; - } - - // Or perhaps a texture, let's invalidate. - InvalidateCache(dest, size, GPU_INVALIDATE_HINT); - return false; -} - -bool GPU_GLES::PerformMemoryDownload(u32 dest, int size) { - // Cheat a bit to force a download of the framebuffer. - // VRAM + 0x00400000 is simply a VRAM mirror. - if (Memory::IsVRAMAddress(dest)) { - return PerformMemoryCopy(dest ^ 0x00400000, dest, size); - } - return false; -} - -bool GPU_GLES::PerformMemoryUpload(u32 dest, int size) { - // Cheat a bit to force an upload of the framebuffer. - // VRAM + 0x00400000 is simply a VRAM mirror. - if (Memory::IsVRAMAddress(dest)) { - return PerformMemoryCopy(dest, dest ^ 0x00400000, size); - } - return false; -} - -bool GPU_GLES::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); - } - return true; - } - return false; -} - void GPU_GLES::ClearCacheNextFrame() { - textureCache_.ClearNextFrame(); -} - -void GPU_GLES::Resized() { - resized_ = true; - framebufferManager_.Resized(); + textureCacheGL_->ClearNextFrame(); } void GPU_GLES::ClearShaderCache() { @@ -2385,7 +2113,7 @@ void GPU_GLES::CleanupBeforeUI() { } std::vector GPU_GLES::GetFramebufferList() { - return framebufferManager_.GetFramebufferList(); + return framebufferManagerGL_->GetFramebufferList(); } void GPU_GLES::DoState(PointerWrap &p) { @@ -2395,21 +2123,21 @@ void GPU_GLES::DoState(PointerWrap &p) { // None of these are necessary when saving. // In Freeze-Frame mode, we don't want to do any of this. if (p.mode == p.MODE_READ && !PSP_CoreParameter().frozen) { - textureCache_.Clear(true); + textureCacheGL_->Clear(true); depalShaderCache_.Clear(); drawEngine_.ClearTrackedVertexArrays(); gstate_c.textureChanged = TEXCHANGE_UPDATED; - framebufferManager_.DestroyAllFBOs(true); + framebufferManagerGL_->DestroyAllFBOs(true); shaderManager_->ClearCache(true); } } bool GPU_GLES::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(); - GEBufferFormat format = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufFormat() : framebufferManager_.DisplayFramebufFormat(); - return framebufferManager_.GetFramebuffer(fb_address, fb_stride, format, buffer, maxRes); + u32 fb_address = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.getFrameBufRawAddress() : framebufferManagerGL_->DisplayFramebufAddr(); + int fb_stride = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufStride() : framebufferManagerGL_->DisplayFramebufStride(); + GEBufferFormat format = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufFormat() : framebufferManagerGL_->DisplayFramebufFormat(); + return framebufferManagerGL_->GetFramebuffer(fb_address, fb_stride, format, buffer, maxRes); } bool GPU_GLES::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) { @@ -2419,14 +2147,14 @@ bool GPU_GLES::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) { u32 z_address = gstate.getDepthBufRawAddress(); int z_stride = gstate.DepthBufStride(); - return framebufferManager_.GetDepthbuffer(fb_address, fb_stride, z_address, z_stride, buffer); + return framebufferManagerGL_->GetDepthbuffer(fb_address, fb_stride, z_address, z_stride, buffer); } bool GPU_GLES::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) { u32 fb_address = gstate.getFrameBufRawAddress(); int fb_stride = gstate.FrameBufStride(); - return framebufferManager_.GetStencilbuffer(fb_address, fb_stride, buffer); + return framebufferManagerGL_->GetStencilbuffer(fb_address, fb_stride, buffer); } bool GPU_GLES::GetCurrentTexture(GPUDebugBuffer &buffer, int level) { @@ -2445,8 +2173,8 @@ bool GPU_GLES::GetCurrentTexture(GPUDebugBuffer &buffer, int level) { gstate.texbufwidth[0] = gstate.texbufwidth[level]; } - textureCache_.SetTexture(true); - textureCache_.ApplyTexture(); + textureCacheGL_->SetTexture(true); + textureCacheGL_->ApplyTexture(); int w = gstate.getTextureWidth(level); int h = gstate.getTextureHeight(level); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w); @@ -2467,7 +2195,7 @@ bool GPU_GLES::GetCurrentTexture(GPUDebugBuffer &buffer, int level) { } bool GPU_GLES::GetCurrentClut(GPUDebugBuffer &buffer) { - return textureCache_.GetCurrentClutBuffer(buffer); + return textureCacheGL_->GetCurrentClutBuffer(buffer); } bool GPU_GLES::GetOutputFramebuffer(GPUDebugBuffer &buffer) { diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index 63f33b57b3..774f6ba208 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -40,24 +40,15 @@ public: // This gets called on startup and when we get back from settings. void CheckGPUFeatures(); - void InitClear() override; - void Reinitialize() override; void PreExecuteOp(u32 op, u32 diff) override; void Execute_Generic(u32 op, u32 diff); void ExecuteOp(u32 op, u32 diff) override; void ReapplyGfxStateInternal() override; void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override; - void CopyDisplayToOutput() override; void BeginFrame() override; void GetStats(char *buffer, size_t bufsize) override; - void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override; - void NotifyVideoUpload(u32 addr, int size, int width, int format) override; - 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; - bool PerformStencilUpload(u32 dest, int size) override; + void ClearCacheNextFrame() override; void DeviceLost() override; // Only happens on Android. Drop all textures and shaders. void DeviceRestore() override; @@ -65,12 +56,10 @@ public: void DumpNextFrame() override; void DoState(PointerWrap &p) override; - // Called by the window system if the window size changed. This will be reflected in PSPCoreParam.pixel*. - void Resized() override; void ClearShaderCache() override; void CleanupBeforeUI() override; bool DecodeTexture(u8 *dest, const GPUgstate &state) override { - return textureCache_.DecodeTexture(dest, state); + return textureCacheGL_->DecodeTexture(dest, state); } bool FramebufferDirty() override; bool FramebufferReallyDirty() override; @@ -160,7 +149,6 @@ public: protected: void FastRunLoop(DisplayList &list) override; - void ProcessEvent(GPUEvent ev) override; void FastLoadBoneMatrix(u32 target) override; void FinishDeferred() override; @@ -168,30 +156,26 @@ private: void Flush() { drawEngine_.Flush(); } - void DoBlockTransfer(u32 skipDrawReason); void CheckFlushOp(int cmd, u32 diff); void BuildReportingInfo(); - void InitClearInternal(); - void BeginFrameInternal(); - void CopyDisplayToOutputInternal(); - 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); - void ReinitializeInternal(); + + void InitClearInternal() override; + void BeginFrameInternal() override; + void CopyDisplayToOutputInternal() override; + void ReinitializeInternal() override; + inline void UpdateVsyncInterval(bool force); void UpdateCmdInfo(); static CommandInfo cmdInfo_[256]; - FramebufferManager framebufferManager_; - TextureCache textureCache_; + FramebufferManager *framebufferManagerGL_; + TextureCache *textureCacheGL_; DepalShaderCache depalShaderCache_; DrawEngineGLES drawEngine_; FragmentTestCache fragmentTestCache_; ShaderManager *shaderManager_; - bool resized_; int lastVsync_; std::string reportingPrimaryInfo_; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 9436393efe..7e8bb73202 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -19,10 +19,16 @@ #include "Core/HLE/sceKernelInterrupt.h" #include "Core/HLE/sceKernelThread.h" #include "Core/HLE/sceGe.h" +#include "Core/Debugger/Breakpoints.h" +#include "Core/MemMapHelpers.h" +#include "GPU/Common/FramebufferCommon.h" +#include "GPU/Common/TextureCacheCommon.h" GPUCommon::GPUCommon() : dumpNextFrame_(false), - dumpThisFrame_(false) + dumpThisFrame_(false), + framebufferManager_(nullptr), + resized_(false) { // This assert failed on GCC x86 32-bit (but not MSVC 32-bit!) before adding the // "padding" field at the end. This is important for save state compatibility. @@ -39,6 +45,7 @@ GPUCommon::GPUCommon() : } GPUCommon::~GPUCommon() { + delete framebufferManager_; } void GPUCommon::BeginHostFrame() { @@ -49,6 +56,14 @@ 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)); @@ -65,6 +80,7 @@ void GPUCommon::Reinitialize() { timeSpentStepping_ = 0.0; interruptsEnabled_ = true; UpdateTickEstimate(0); + ScheduleEvent(GPU_EVENT_REINITIALIZE); } void GPUCommon::PopDLQueue() { @@ -93,6 +109,11 @@ bool GPUCommon::BusyDrawing() { return false; } +void GPUCommon::Resized() { + resized_ = true; + framebufferManager_->Resized(); +} + u32 GPUCommon::DrawSync(int mode) { if (ThreadEnabled()) { // Sync first, because the CPU is usually faster than the emulated GPU. @@ -677,8 +698,37 @@ void GPUCommon::ProcessEvent(GPUEvent ev) { 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; + default: ERROR_LOG_REPORT(G3D, "Unexpected GPU event type: %d", (int)ev); + break; } } @@ -1312,3 +1362,224 @@ void GPUCommon::AdvanceVerts(u32 vertType, int count, int bytesRead) { gstate_c.vertexAddr += bytesRead; } } + + +void GPUCommon::DoBlockTransfer(u32 skipDrawReason) { + // TODO: This is used a lot to copy data around between render targets and textures, + // and also to quickly load textures from RAM to VRAM. So we should do checks like the following: + // * Does dstBasePtr point to an existing texture? If so maybe reload it immediately. + // + // * Does srcBasePtr point to a render target, and dstBasePtr to a texture? If so + // either copy between rt and texture or reassign the texture to point to the render target + // + // etc.... + + u32 srcBasePtr = gstate.getTransferSrcAddress(); + u32 srcStride = gstate.getTransferSrcStride(); + + u32 dstBasePtr = gstate.getTransferDstAddress(); + u32 dstStride = gstate.getTransferDstStride(); + + int srcX = gstate.getTransferSrcX(); + int srcY = gstate.getTransferSrcY(); + + int dstX = gstate.getTransferDstX(); + int dstY = gstate.getTransferDstY(); + + int width = gstate.getTransferWidth(); + int height = gstate.getTransferHeight(); + + int bpp = gstate.getTransferBpp(); + + DEBUG_LOG(G3D, "Block transfer: %08x/%x -> %08x/%x, %ix%ix%i (%i,%i)->(%i,%i)", srcBasePtr, srcStride, dstBasePtr, dstStride, width, height, bpp, srcX, srcY, dstX, dstY); + + if (!Memory::IsValidAddress(srcBasePtr)) { + ERROR_LOG_REPORT(G3D, "BlockTransfer: Bad source transfer address %08x!", srcBasePtr); + return; + } + + if (!Memory::IsValidAddress(dstBasePtr)) { + ERROR_LOG_REPORT(G3D, "BlockTransfer: Bad destination transfer address %08x!", dstBasePtr); + return; + } + + // Check that the last address of both source and dest are valid addresses + + u32 srcLastAddr = srcBasePtr + ((srcY + height - 1) * srcStride + (srcX + width - 1)) * bpp; + u32 dstLastAddr = dstBasePtr + ((dstY + height - 1) * dstStride + (dstX + width - 1)) * bpp; + + if (!Memory::IsValidAddress(srcLastAddr)) { + ERROR_LOG_REPORT(G3D, "Bottom-right corner of source of block transfer is at an invalid address: %08x", srcLastAddr); + return; + } + if (!Memory::IsValidAddress(dstLastAddr)) { + ERROR_LOG_REPORT(G3D, "Bottom-right corner of destination of block transfer is at an invalid address: %08x", srcLastAddr); + return; + } + + // Tell the framebuffer manager to take action if possible. If it does the entire thing, let's just return. + if (!framebufferManager_->NotifyBlockTransferBefore(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason)) { + // Do the copy! (Hm, if we detect a drawn video frame (see below) then we could maybe skip this?) + // Can use GetPointerUnchecked because we checked the addresses above. We could also avoid them + // entirely by walking a couple of pointers... + if (srcStride == dstStride && (u32)width == srcStride) { + // Common case in God of War, let's do it all in one chunk. + u32 srcLineStartAddr = srcBasePtr + (srcY * srcStride + srcX) * bpp; + u32 dstLineStartAddr = dstBasePtr + (dstY * dstStride + dstX) * bpp; + const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr); + u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr); + memcpy(dst, src, width * height * bpp); + } else { + for (int y = 0; y < height; y++) { + u32 srcLineStartAddr = srcBasePtr + ((y + srcY) * srcStride + srcX) * bpp; + u32 dstLineStartAddr = dstBasePtr + ((y + dstY) * dstStride + dstX) * bpp; + + const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr); + u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr); + memcpy(dst, src, width * bpp); + } + } + + textureCache_->Invalidate(dstBasePtr + (dstY * dstStride + dstX) * bpp, height * dstStride * bpp, GPU_INVALIDATE_HINT); + framebufferManager_->NotifyBlockTransferAfter(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason); + } + +#ifndef MOBILE_DEVICE + CBreakPoints::ExecMemCheck(srcBasePtr + (srcY * srcStride + srcX) * bpp, false, height * srcStride * bpp, currentMIPS->pc); + CBreakPoints::ExecMemCheck(dstBasePtr + (srcY * dstStride + srcX) * bpp, true, height * dstStride * bpp, currentMIPS->pc); +#endif + + // TODO: Correct timing appears to be 1.9, but erring a bit low since some of our other timing is inaccurate. + 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); + } + return true; + } + + InvalidateCache(dest, size, GPU_INVALIDATE_HINT); + return false; +} + +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); + } + return true; + } + + // Or perhaps a texture, let's invalidate. + InvalidateCache(dest, size, GPU_INVALIDATE_HINT); + return false; +} + +bool GPUCommon::PerformMemoryDownload(u32 dest, int size) { + // Cheat a bit to force a download of the framebuffer. + // VRAM + 0x00400000 is simply a VRAM mirror. + if (Memory::IsVRAMAddress(dest)) { + return PerformMemoryCopy(dest ^ 0x00400000, dest, size); + } + return false; +} + +bool GPUCommon::PerformMemoryUpload(u32 dest, int size) { + // Cheat a bit to force an upload of the framebuffer. + // VRAM + 0x00400000 is simply a VRAM mirror. + if (Memory::IsVRAMAddress(dest)) { + return PerformMemoryCopy(dest, dest ^ 0x00400000, size); + } + return false; +} + +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 + textureCache_->InvalidateAll(type); + + if (type != GPU_INVALIDATE_ALL && framebufferManager_->MayIntersectFramebuffer(addr)) { + // If we're doing block transfers, we shouldn't need this, and it'll only confuse us. + // Vempire invalidates (with writeback) after drawing, but before blitting. + if (!g_Config.bBlockTransferGPU || type == GPU_INVALIDATE_SAFE) { + framebufferManager_->UpdateFromMemory(addr, size, type == GPU_INVALIDATE_SAFE); + } + } +} + +void GPUCommon::NotifyVideoUpload(u32 addr, int size, int width, int format) { + if (Memory::IsVRAMAddress(addr)) { + framebufferManager_->NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); + } + textureCache_->NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); + InvalidateCache(addr, size, GPU_INVALIDATE_SAFE); +} + +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); + } + return true; + } + return false; +} + +void GPUCommon::PerformStencilUploadInternal(u32 dest, int size) { + framebufferManager_->NotifyStencilUpload(dest, size); +} diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 94519e2a0a..271373f5a9 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -14,6 +14,9 @@ typedef ThreadEventQueue GPUThreadEventQueue; +class FramebufferManagerCommon; +class TextureCacheCommon; + class GPUCommon : public GPUThreadEventQueue, public GPUDebugInterface { public: GPUCommon(); @@ -31,6 +34,8 @@ public: interruptsEnabled_ = enable; } + void Resized() override; + void ExecuteOp(u32 op, u32 diff) override; void PreExecuteOp(u32 op, u32 diff) override; bool InterpretList(DisplayList &list) override; @@ -55,6 +60,17 @@ public: u32 Break(int mode) override; void ReapplyGfxState() override; + void CopyDisplayToOutput() override; + void InitClear() override; + 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; + + 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; + void Execute_OffsetAddr(u32 op, u32 diff); void Execute_Origin(u32 op, u32 diff); void Execute_Jump(u32 op, u32 diff); @@ -135,6 +151,11 @@ public: } protected: + virtual void InitClearInternal() {} + virtual void BeginFrameInternal() {} + virtual void CopyDisplayToOutputInternal() {} + virtual void ReinitializeInternal() {} + // To avoid virtual calls to PreExecuteOp(). virtual void FastRunLoop(DisplayList &list) = 0; void SlowRunLoop(DisplayList &list); @@ -156,8 +177,15 @@ protected: virtual void FinishDeferred() { } + void DoBlockTransfer(u32 skipDrawReason); + void AdvanceVerts(u32 vertType, int count, int bytesRead); + 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); + // Allows early unlocking with a guard. Do not double unlock. class easy_guard { public: @@ -170,6 +198,9 @@ protected: bool locked_; }; + FramebufferManagerCommon *framebufferManager_; + TextureCacheCommon *textureCache_; + typedef std::list DisplayListQueue; int nextListID; @@ -192,8 +223,10 @@ protected: bool dumpNextFrame_; bool dumpThisFrame_; bool interruptsEnabled_; + bool resized_; private: + // For CPU/GPU sync. #ifdef __ANDROID__ alignas(16) std::atomic curTickEst_; diff --git a/GPU/Vulkan/FramebufferVulkan.h b/GPU/Vulkan/FramebufferVulkan.h index d1742b8c1d..b72f2405e1 100644 --- a/GPU/Vulkan/FramebufferVulkan.h +++ b/GPU/Vulkan/FramebufferVulkan.h @@ -102,7 +102,7 @@ public: void BeginFrameVulkan(); // there's a BeginFrame in the base class, which this calls void EndFrame(); - void Resized(); + void Resized() override; void DeviceLost(); void DeviceRestore(VulkanContext *vulkan); void CopyDisplayToOutput(); diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 0405b3fc9c..f26cacb090 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -393,26 +393,28 @@ static const CommandTableEntry commandTable[] = { GPU_Vulkan::GPU_Vulkan(GraphicsContext *ctx) : vulkan_((VulkanContext *)ctx->GetAPIContext()), drawEngine_(vulkan_), - textureCache_(vulkan_), - resized_(false), gfxCtx_(ctx) { UpdateVsyncInterval(true); CheckGPUFeatures(); shaderManager_ = new ShaderManagerVulkan(vulkan_); pipelineManager_ = new PipelineManagerVulkan(vulkan_); - framebufferManager_ = new FramebufferManagerVulkan(vulkan_); - drawEngine_.SetTextureCache(&textureCache_); - drawEngine_.SetFramebufferManager(framebufferManager_); + framebufferManagerVulkan_ = new FramebufferManagerVulkan(vulkan_); + framebufferManager_ = framebufferManagerVulkan_; + textureCacheVulkan_ = new TextureCacheVulkan(vulkan_); + textureCache_ = textureCacheVulkan_; + + drawEngine_.SetTextureCache(textureCacheVulkan_); + drawEngine_.SetFramebufferManager(framebufferManagerVulkan_); drawEngine_.SetShaderManager(shaderManager_); drawEngine_.SetPipelineManager(pipelineManager_); - framebufferManager_->Init(); - framebufferManager_->SetTextureCache(&textureCache_); - framebufferManager_->SetDrawEngine(&drawEngine_); - textureCache_.SetFramebufferManager(framebufferManager_); - textureCache_.SetDepalShaderCache(&depalShaderCache_); - textureCache_.SetShaderManager(shaderManager_); - textureCache_.SetTransformDrawEngine(&drawEngine_); + framebufferManagerVulkan_->Init(); + framebufferManagerVulkan_->SetTextureCache(textureCacheVulkan_); + framebufferManagerVulkan_->SetDrawEngine(&drawEngine_); + textureCacheVulkan_->SetFramebufferManager(framebufferManagerVulkan_); + textureCacheVulkan_->SetDepalShaderCache(&depalShaderCache_); + textureCacheVulkan_->SetShaderManager(shaderManager_); + textureCacheVulkan_->SetTransformDrawEngine(&drawEngine_); // Sanity check gstate if ((int *)&gstate.transferstart - (int *)&gstate != 0xEA) { @@ -448,13 +450,12 @@ GPU_Vulkan::GPU_Vulkan(GraphicsContext *ctx) // Update again after init to be sure of any silly driver problems. UpdateVsyncInterval(true); - textureCache_.NotifyConfigChanged(); + textureCacheVulkan_->NotifyConfigChanged(); } GPU_Vulkan::~GPU_Vulkan() { - framebufferManager_->DestroyAllFBOs(true); + framebufferManagerVulkan_->DestroyAllFBOs(true); depalShaderCache_.Clear(); - delete framebufferManager_; delete pipelineManager_; delete shaderManager_; } @@ -495,14 +496,14 @@ void GPU_Vulkan::BeginHostFrame() { BuildReportingInfo(); UpdateCmdInfo(); drawEngine_.Resized(); - textureCache_.NotifyConfigChanged(); + textureCacheVulkan_->NotifyConfigChanged(); } resized_ = false; - textureCache_.StartFrame(); + textureCacheVulkan_->StartFrame(); depalShaderCache_.Decimate(); - framebufferManager_->BeginFrameVulkan(); + framebufferManagerVulkan_->BeginFrameVulkan(); shaderManager_->DirtyShader(); shaderManager_->DirtyUniform(DIRTY_ALL); @@ -518,8 +519,8 @@ void GPU_Vulkan::BeginHostFrame() { void GPU_Vulkan::EndHostFrame() { drawEngine_.EndFrame(); - framebufferManager_->EndFrame(); - textureCache_.EndFrame(); + framebufferManagerVulkan_->EndFrame(); + textureCacheVulkan_->EndFrame(); } // Needs to be called on GPU thread, not reporting thread. @@ -600,20 +601,11 @@ void GPU_Vulkan::BuildReportingInfo() { Reporting::UpdateConfig(); } -void GPU_Vulkan::InitClear() { - ScheduleEvent(GPU_EVENT_INIT_CLEAR); -} - -void GPU_Vulkan::Reinitialize() { - GPUCommon::Reinitialize(); - ScheduleEvent(GPU_EVENT_REINITIALIZE); -} - void GPU_Vulkan::ReinitializeInternal() { - textureCache_.Clear(true); + textureCacheVulkan_->Clear(true); depalShaderCache_.Clear(); - framebufferManager_->DestroyAllFBOs(true); - framebufferManager_->Resized(); + framebufferManagerVulkan_->DestroyAllFBOs(true); + framebufferManagerVulkan_->Resized(); } void GPU_Vulkan::InitClearInternal() { @@ -651,10 +643,6 @@ void GPU_Vulkan::UpdateCmdInfo() { // } } -void GPU_Vulkan::ReapplyGfxStateInternal() { - GPUCommon::ReapplyGfxStateInternal(); -} - void GPU_Vulkan::BeginFrameInternal() { } @@ -693,17 +681,13 @@ bool GPU_Vulkan::FramebufferReallyDirty() { return true; } -void GPU_Vulkan::CopyDisplayToOutput() { - ScheduleEvent(GPU_EVENT_COPY_DISPLAY_TO_OUTPUT); -} - void GPU_Vulkan::CopyDisplayToOutputInternal() { // Flush anything left over. drawEngine_.Flush(curCmd_); shaderManager_->DirtyLastShader(); - framebufferManager_->CopyDisplayToOutput(); + framebufferManagerVulkan_->CopyDisplayToOutput(); gstate_c.textureChanged = TEXCHANGE_UPDATED; } @@ -738,45 +722,6 @@ void GPU_Vulkan::FastRunLoop(DisplayList &list) { void GPU_Vulkan::FinishDeferred() { } -void GPU_Vulkan::ProcessEvent(GPUEvent ev) { - switch (ev.type) { - 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: - ReinitializeInternal(); - break; - - default: - GPUCommon::ProcessEvent(ev); - } -} - inline void GPU_Vulkan::CheckFlushOp(int cmd, u32 diff) { const u8 cmdFlags = cmdInfo_[cmd].flags; if ((cmdFlags & FLAG_FLUSHBEFORE) || (diff && (cmdFlags & FLAG_FLUSHBEFOREONCHANGE))) { @@ -1107,7 +1052,7 @@ void GPU_Vulkan::Execute_TexLevel(u32 op, u32 diff) { void GPU_Vulkan::Execute_LoadClut(u32 op, u32 diff) { gstate_c.textureChanged |= TEXCHANGE_PARAMSONLY; - textureCache_.LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes()); + textureCacheVulkan_->LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes()); // This could be used to "dirty" textures with clut. } @@ -1936,10 +1881,10 @@ void GPU_Vulkan::FastLoadBoneMatrix(u32 target) { } void GPU_Vulkan::DeviceLost() { - framebufferManager_->DeviceLost(); + framebufferManagerVulkan_->DeviceLost(); drawEngine_.DeviceLost(); pipelineManager_->DeviceLost(); - textureCache_.DeviceLost(); + textureCacheVulkan_->DeviceLost(); depalShaderCache_.Clear(); shaderManager_->ClearShaders(); } @@ -1950,10 +1895,10 @@ void GPU_Vulkan::DeviceRestore() { BuildReportingInfo(); UpdateCmdInfo(); - framebufferManager_->DeviceRestore(vulkan_); + framebufferManagerVulkan_->DeviceRestore(vulkan_); drawEngine_.DeviceRestore(vulkan_); pipelineManager_->DeviceRestore(vulkan_); - textureCache_.DeviceRestore(vulkan_); + textureCacheVulkan_->DeviceRestore(vulkan_); shaderManager_->DeviceRestore(vulkan_); } @@ -1985,7 +1930,7 @@ void GPU_Vulkan::GetStats(char *buffer, size_t bufsize) { gpuStats.numCachedVertsDrawn, gpuStats.numUncachedVertsDrawn, (int)framebufferManager_->NumVFBs(), - (int)textureCache_.NumLoadedTextures(), + (int)textureCacheVulkan_->NumLoadedTextures(), gpuStats.numTexturesDecoded, gpuStats.numTextureInvalidations, shaderManager_->GetNumVertexShaders(), @@ -1997,234 +1942,8 @@ void GPU_Vulkan::GetStats(char *buffer, size_t bufsize) { ); } -void GPU_Vulkan::DoBlockTransfer(u32 skipDrawReason) { - // TODO: This is used a lot to copy data around between render targets and textures, - // and also to quickly load textures from RAM to VRAM. So we should do checks like the following: - // * Does dstBasePtr point to an existing texture? If so maybe reload it immediately. - // - // * Does srcBasePtr point to a render target, and dstBasePtr to a texture? If so - // either copy between rt and texture or reassign the texture to point to the render target - // - // etc.... - - u32 srcBasePtr = gstate.getTransferSrcAddress(); - u32 srcStride = gstate.getTransferSrcStride(); - - u32 dstBasePtr = gstate.getTransferDstAddress(); - u32 dstStride = gstate.getTransferDstStride(); - - int srcX = gstate.getTransferSrcX(); - int srcY = gstate.getTransferSrcY(); - - int dstX = gstate.getTransferDstX(); - int dstY = gstate.getTransferDstY(); - - int width = gstate.getTransferWidth(); - int height = gstate.getTransferHeight(); - - int bpp = gstate.getTransferBpp(); - - DEBUG_LOG(G3D, "Block transfer: %08x/%x -> %08x/%x, %ix%ix%i (%i,%i)->(%i,%i)", srcBasePtr, srcStride, dstBasePtr, dstStride, width, height, bpp, srcX, srcY, dstX, dstY); - - if (!Memory::IsValidAddress(srcBasePtr)) { - ERROR_LOG_REPORT(G3D, "BlockTransfer: Bad source transfer address %08x!", srcBasePtr); - return; - } - - if (!Memory::IsValidAddress(dstBasePtr)) { - ERROR_LOG_REPORT(G3D, "BlockTransfer: Bad destination transfer address %08x!", dstBasePtr); - return; - } - - // Check that the last address of both source and dest are valid addresses - - u32 srcLastAddr = srcBasePtr + ((srcY + height - 1) * srcStride + (srcX + width - 1)) * bpp; - u32 dstLastAddr = dstBasePtr + ((dstY + height - 1) * dstStride + (dstX + width - 1)) * bpp; - - if (!Memory::IsValidAddress(srcLastAddr)) { - ERROR_LOG_REPORT(G3D, "Bottom-right corner of source of block transfer is at an invalid address: %08x", srcLastAddr); - return; - } - if (!Memory::IsValidAddress(dstLastAddr)) { - ERROR_LOG_REPORT(G3D, "Bottom-right corner of destination of block transfer is at an invalid address: %08x", srcLastAddr); - return; - } - - // Tell the framebuffer manager to take action if possible. If it does the entire thing, let's just return. - if (!framebufferManager_->NotifyBlockTransferBefore(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason)) { - // Do the copy! (Hm, if we detect a drawn video frame (see below) then we could maybe skip this?) - // Can use GetPointerUnchecked because we checked the addresses above. We could also avoid them - // entirely by walking a couple of pointers... - if (srcStride == dstStride && (u32)width == srcStride) { - // Common case in God of War, let's do it all in one chunk. - u32 srcLineStartAddr = srcBasePtr + (srcY * srcStride + srcX) * bpp; - u32 dstLineStartAddr = dstBasePtr + (dstY * dstStride + dstX) * bpp; - const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr); - u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr); - memcpy(dst, src, width * height * bpp); - } else { - for (int y = 0; y < height; y++) { - u32 srcLineStartAddr = srcBasePtr + ((y + srcY) * srcStride + srcX) * bpp; - u32 dstLineStartAddr = dstBasePtr + ((y + dstY) * dstStride + dstX) * bpp; - - const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr); - u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr); - memcpy(dst, src, width * bpp); - } - } - - textureCache_.Invalidate(dstBasePtr + (dstY * dstStride + dstX) * bpp, height * dstStride * bpp, GPU_INVALIDATE_HINT); - framebufferManager_->NotifyBlockTransferAfter(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason); - } - -#ifndef MOBILE_DEVICE - CBreakPoints::ExecMemCheck(srcBasePtr + (srcY * srcStride + srcX) * bpp, false, height * srcStride * bpp, currentMIPS->pc); - CBreakPoints::ExecMemCheck(dstBasePtr + (srcY * dstStride + srcX) * bpp, true, height * dstStride * bpp, currentMIPS->pc); -#endif - - // TODO: Correct timing appears to be 1.9, but erring a bit low since some of our other timing is inaccurate. - cyclesExecuted += ((height * width * bpp) * 16) / 10; -} - -void GPU_Vulkan::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 GPU_Vulkan::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type) { - if (size > 0) - textureCache_.Invalidate(addr, size, type); - else - textureCache_.InvalidateAll(type); - - if (type != GPU_INVALIDATE_ALL && framebufferManager_->MayIntersectFramebuffer(addr)) { - // If we're doing block transfers, we shouldn't need this, and it'll only confuse us. - // Vempire invalidates (with writeback) after drawing, but before blitting. - if (!g_Config.bBlockTransferGPU || type == GPU_INVALIDATE_SAFE) { - framebufferManager_->UpdateFromMemory(addr, size, type == GPU_INVALIDATE_SAFE); - } - } -} - -void GPU_Vulkan::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 GPU_Vulkan::PerformMemorySetInternal(u32 dest, u8 v, int size) { - if (!framebufferManager_->NotifyFramebufferCopy(dest, dest, size, true, gstate_c.skipDrawReason)) { - InvalidateCache(dest, size, GPU_INVALIDATE_HINT); - } -} - -void GPU_Vulkan::PerformStencilUploadInternal(u32 dest, int size) { - framebufferManager_->NotifyStencilUpload(dest, size); -} - -bool GPU_Vulkan::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); - } - return true; - } - - InvalidateCache(dest, size, GPU_INVALIDATE_HINT); - return false; -} - -bool GPU_Vulkan::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); - } - return true; - } - - // Or perhaps a texture, let's invalidate. - InvalidateCache(dest, size, GPU_INVALIDATE_HINT); - return false; -} - -void GPU_Vulkan::NotifyVideoUpload(u32 addr, int size, int width, int format) { - if (Memory::IsVRAMAddress(addr)) { - // TODO - //framebufferManager_.NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); - } - textureCache_.NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); - InvalidateCache(addr, size, GPU_INVALIDATE_SAFE); -} - -bool GPU_Vulkan::PerformMemoryDownload(u32 dest, int size) { - // Cheat a bit to force a download of the framebuffer. - // VRAM + 0x00400000 is simply a VRAM mirror. - if (Memory::IsVRAMAddress(dest)) { - return PerformMemoryCopy(dest ^ 0x00400000, dest, size); - } - return false; -} - -bool GPU_Vulkan::PerformMemoryUpload(u32 dest, int size) { - // Cheat a bit to force an upload of the framebuffer. - // VRAM + 0x00400000 is simply a VRAM mirror. - if (Memory::IsVRAMAddress(dest)) { - return PerformMemoryCopy(dest, dest ^ 0x00400000, size); - } - return false; -} - -bool GPU_Vulkan::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); - } - return true; - } - return false; -} - void GPU_Vulkan::ClearCacheNextFrame() { - textureCache_.ClearNextFrame(); -} - -void GPU_Vulkan::Resized() { - resized_ = true; - framebufferManager_->Resized(); + textureCacheVulkan_->ClearNextFrame(); } void GPU_Vulkan::ClearShaderCache() { @@ -2232,7 +1951,7 @@ void GPU_Vulkan::ClearShaderCache() { } std::vector GPU_Vulkan::GetFramebufferList() { - return framebufferManager_->GetFramebufferList(); + return framebufferManagerVulkan_->GetFramebufferList(); } void GPU_Vulkan::DoState(PointerWrap &p) { @@ -2242,11 +1961,11 @@ void GPU_Vulkan::DoState(PointerWrap &p) { // None of these are necessary when saving. // In Freeze-Frame mode, we don't want to do any of this. if (p.mode == p.MODE_READ && !PSP_CoreParameter().frozen) { - textureCache_.Clear(true); + textureCacheVulkan_->Clear(true); depalShaderCache_.Clear(); gstate_c.textureChanged = TEXCHANGE_UPDATED; - framebufferManager_->DestroyAllFBOs(true); + framebufferManagerVulkan_->DestroyAllFBOs(true); shaderManager_->ClearShaders(); pipelineManager_->Clear(); } diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 7aa67b18fa..837b066f90 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -42,24 +42,13 @@ public: void BeginHostFrame() override; void EndHostFrame() override; - void InitClear() override; - void Reinitialize() override; void PreExecuteOp(u32 op, u32 diff) override; void Execute_Generic(u32 op, u32 diff); void ExecuteOp(u32 op, u32 diff) override; - void ReapplyGfxStateInternal() override; void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override; - void CopyDisplayToOutput() override; - void NotifyVideoUpload(u32 addr, int size, int width, int format) override; void BeginFrame() override; void GetStats(char *buffer, size_t bufsize) override; - void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override; - 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; - bool PerformStencilUpload(u32 dest, int size) override; void ClearCacheNextFrame() override; void DeviceLost() override; // Only happens on Android. Drop all textures and shaders. void DeviceRestore() override; @@ -67,8 +56,6 @@ public: void DumpNextFrame() override; void DoState(PointerWrap &p) override; - // Called by the window system if the window size changed. This will be reflected in PSPCoreParam.pixel*. - void Resized() override; void ClearShaderCache() override; bool DecodeTexture(u8 *dest, const GPUgstate &state) override { return false; @@ -150,10 +137,8 @@ public: bool GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices) override; bool DescribeCodePtr(const u8 *ptr, std::string &name) override; - protected: void FastRunLoop(DisplayList &list) override; - void ProcessEvent(GPUEvent ev) override; void FastLoadBoneMatrix(u32 target) override; void FinishDeferred() override; @@ -161,25 +146,20 @@ private: void Flush() { drawEngine_.Flush(nullptr); } - void DoBlockTransfer(u32 skipDrawReason); void CheckFlushOp(int cmd, u32 diff); void BuildReportingInfo(); - void InitClearInternal(); - void BeginFrameInternal(); - void CopyDisplayToOutputInternal(); - 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); - void ReinitializeInternal(); + void InitClearInternal() override; + void BeginFrameInternal() override; + void CopyDisplayToOutputInternal() override; + void ReinitializeInternal() override; inline void UpdateVsyncInterval(bool force); void UpdateCmdInfo(); static CommandInfo cmdInfo_[256]; GraphicsContext *gfxCtx_; VulkanContext *vulkan_; - FramebufferManagerVulkan *framebufferManager_; - TextureCacheVulkan textureCache_; + FramebufferManagerVulkan *framebufferManagerVulkan_; + TextureCacheVulkan *textureCacheVulkan_; DepalShaderCacheVulkan depalShaderCache_; DrawEngineVulkan drawEngine_; @@ -189,7 +169,6 @@ private: // Manages state and pipeline objects PipelineManagerVulkan *pipelineManager_; - bool resized_; int lastVsync_; VkCommandBuffer curCmd_; diff --git a/GPU/Vulkan/TextureCacheVulkan.h b/GPU/Vulkan/TextureCacheVulkan.h index b0fe471449..213c43e491 100644 --- a/GPU/Vulkan/TextureCacheVulkan.h +++ b/GPU/Vulkan/TextureCacheVulkan.h @@ -95,8 +95,8 @@ public: void Clear(bool delete_them); void StartFrame(); void EndFrame(); - void Invalidate(u32 addr, int size, GPUInvalidationType type); - void InvalidateAll(GPUInvalidationType type); + void Invalidate(u32 addr, int size, GPUInvalidationType type) override; + void InvalidateAll(GPUInvalidationType type) override; void ClearNextFrame(); void DeviceLost();