From e7e7528fbcd5d41113281d081c85d7900c16347e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 9 Oct 2022 00:50:45 -0700 Subject: [PATCH 1/4] GPU: Consider depth buffers in block transfer. Right now, only with an explicit flag (not yet used.) --- GPU/Common/FramebufferManagerCommon.cpp | 42 ++++++++++++++++++++----- GPU/GPUInterface.h | 3 +- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index df0342724afc..17c618c43a4d 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -1657,13 +1657,14 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, VirtualFramebuffer *srcBuffer = nullptr; bool ignoreDstBuffer = flags & GPUCopyFlag::FORCE_DST_MEM; bool ignoreSrcBuffer = flags & (GPUCopyFlag::FORCE_SRC_MEM | GPUCopyFlag::MEMSET); + RasterChannel channel = flags & GPUCopyFlag::DEPTH_REQUESTED ? RASTER_DEPTH : RASTER_COLOR; u32 dstY = (u32)-1; u32 dstH = 0; u32 srcY = (u32)-1; u32 srcH = 0; for (auto vfb : vfbs_) { - if (vfb->fb_stride == 0) { + if (vfb->fb_stride == 0 || channel != RASTER_COLOR) { continue; } @@ -1715,14 +1716,36 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, } } + if (channel == RASTER_DEPTH) { + srcBuffer = nullptr; + dstBuffer = nullptr; + // Let's assume exact matches only for simplicity. + for (auto vfb : vfbs_) { + if (!ignoreDstBuffer && dst == vfb->z_address && size == vfb->z_stride * 2 * vfb->height) { + if (!dstBuffer || dstBuffer->depthBindSeq < vfb->depthBindSeq) { + dstBuffer = vfb; + dstY = 0; + dstH = vfb->height; + } + } + if (!ignoreSrcBuffer && src == vfb->z_address && size == vfb->z_stride * 2 * vfb->height) { + if (!srcBuffer || srcBuffer->depthBindSeq < vfb->depthBindSeq) { + srcBuffer = vfb; + srcY = 0; + srcH = vfb->height; + } + } + } + } + if (!useBufferedRendering_) { // If we're copying into a recently used display buf, it's probably destined for the screen. - if (srcBuffer || (dstBuffer != displayFramebuf_ && dstBuffer != prevDisplayFramebuf_)) { + if (channel == RASTER_DEPTH || srcBuffer || (dstBuffer != displayFramebuf_ && dstBuffer != prevDisplayFramebuf_)) { return false; } } - if (!dstBuffer && srcBuffer) { + if (!dstBuffer && srcBuffer && channel != RASTER_DEPTH) { // Note - if we're here, we're in a memcpy, not a block transfer. Not allowing IntraVRAMBlockTransferAllowCreateFB. // Technically, that makes BlockTransferAllowCreateFB a bit of a misnomer. if (PSP_CoreParameter().compat.flags().BlockTransferAllowCreateFB) { @@ -1740,7 +1763,7 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, } else { WARN_LOG_ONCE(dstnotsrccpy, G3D, "Inter-buffer memcpy %08x -> %08x (size: %x)", src, dst, size); // Just do the blit! - BlitFramebuffer(dstBuffer, 0, dstY, srcBuffer, 0, srcY, srcBuffer->width, srcH, 0, RASTER_COLOR, "Blit_InterBufferMemcpy"); + BlitFramebuffer(dstBuffer, 0, dstY, srcBuffer, 0, srcY, srcBuffer->width, srcH, 0, channel, "Blit_InterBufferMemcpy"); SetColorUpdated(dstBuffer, skipDrawReason); RebindFramebuffer("RebindFramebuffer - Inter-buffer memcpy"); } @@ -1752,7 +1775,9 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, WARN_LOG_ONCE(btucpy, G3D, "Memcpy fbo upload %08x -> %08x (size: %x)", src, dst, size); FlushBeforeCopy(); const u8 *srcBase = Memory::GetPointerUnchecked(src); - DrawPixels(dstBuffer, 0, dstY, srcBase, dstBuffer->fb_format, dstBuffer->fb_stride, dstBuffer->width, dstH, RASTER_COLOR, "MemcpyFboUpload_DrawPixels"); + GEBufferFormat srcFormat = channel == RASTER_DEPTH ? GE_FORMAT_DEPTH16 : dstBuffer->fb_format; + int srcStride = channel == RASTER_DEPTH ? dstBuffer->z_stride : dstBuffer->fb_stride; + DrawPixels(dstBuffer, 0, dstY, srcBase, srcFormat, srcStride, dstBuffer->width, dstH, channel, "MemcpyFboUpload_DrawPixels"); SetColorUpdated(dstBuffer, skipDrawReason); RebindFramebuffer("RebindFramebuffer - Memcpy fbo upload"); // This is a memcpy, let's still copy just in case. @@ -1762,8 +1787,8 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, FlushBeforeCopy(); if (srcH == 0 || srcY + srcH > srcBuffer->bufferHeight) { WARN_LOG_ONCE(btdcpyheight, G3D, "Memcpy fbo download %08x -> %08x skipped, %d+%d is taller than %d", src, dst, srcY, srcH, srcBuffer->bufferHeight); - } else if (g_Config.bBlockTransferGPU && !srcBuffer->memoryUpdated) { - ReadFramebufferToMemory(srcBuffer, 0, srcY, srcBuffer->width, srcH, RASTER_COLOR); + } else if (g_Config.bBlockTransferGPU && (!srcBuffer->memoryUpdated || channel == RASTER_DEPTH)) { + ReadFramebufferToMemory(srcBuffer, 0, srcY, srcBuffer->width, srcH, channel); srcBuffer->usageFlags = (srcBuffer->usageFlags | FB_USAGE_DOWNLOAD) & ~FB_USAGE_DOWNLOAD_CLEAR; } return false; @@ -2623,7 +2648,8 @@ void FramebufferManagerCommon::ReadFramebufferToMemory(VirtualFramebuffer *vfb, vfb->usageFlags |= FB_USAGE_DOWNLOAD; } else if (x == 0 && y == 0 && w == vfb->width && h == vfb->height) { // Mark it as fully downloaded until next render to it. - vfb->memoryUpdated = true; + if (channel == RASTER_COLOR) + vfb->memoryUpdated = true; vfb->usageFlags |= FB_USAGE_DOWNLOAD; } else { // Let's try to set the flag eventually, if the game copies a lot. diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index e7cf2f9af6fc..3a71b550b470 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -120,7 +120,8 @@ enum class GPUCopyFlag { FORCE_DST_MEM = 2, // Note: implies src == dst and FORCE_SRC_MEM. MEMSET = 4, - DEBUG_NOTIFIED = 8, + DEPTH_REQUESTED = 8, + DEBUG_NOTIFIED = 16, }; ENUM_CLASS_BITOPS(GPUCopyFlag); From 057661380efc6e31bf634b1eca4d24a7e805f5fa Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 9 Oct 2022 00:52:35 -0700 Subject: [PATCH 2/4] GPU: Hook Gods Eater Burst avatar read. Currently not working since depth comes back as 0. --- Core/HLE/ReplaceTables.cpp | 30 ++++++++++++++++++++++++++++++ Core/MIPS/MIPSAnalyst.cpp | 1 + 2 files changed, 31 insertions(+) diff --git a/Core/HLE/ReplaceTables.cpp b/Core/HLE/ReplaceTables.cpp index 462bad0a7e02..cc4777af9802 100644 --- a/Core/HLE/ReplaceTables.cpp +++ b/Core/HLE/ReplaceTables.cpp @@ -691,6 +691,35 @@ static int Hook_godseaterburst_blit_texture() { return 0; } +static int Hook_godseaterburst_depthmask_5551() { + // This function copies the 5551 framebuffer to a temporary, generating alpha based on depth. + // Depth is optional, in which case all pixels get full alpha. + // Called when your avatar changes to screenshot for save data. + uint32_t colorBuffer = currentMIPS->r[MIPS_REG_A1]; + uint32_t depthBuffer = currentMIPS->r[MIPS_REG_T2]; + uint32_t byteStride = currentMIPS->r[MIPS_REG_A2]; + uint32_t height = currentMIPS->r[MIPS_REG_T1]; + uint32_t size = byteStride * height; + + if (!Memory::IsVRAMAddress(colorBuffer) || !Memory::IsValidRange(colorBuffer, size)) + return 0; + if (depthBuffer != 0) { + if (!Memory::IsVRAMAddress(colorBuffer) || !Memory::IsValidRange(depthBuffer, size)) + return 0; + + // This is added to read from the linearized mirror. + uint32_t depthMirror = depthBuffer + 0x00200000; + // Depth download required, or it won't work and will be transparent. + gpu->PerformMemoryCopy(depthMirror, depthMirror, size, GPUCopyFlag::FORCE_DST_MEM | GPUCopyFlag::DEPTH_REQUESTED); + NotifyMemInfo(MemBlockFlags::WRITE, depthMirror, size, "godseaterburst_depthmask_5551"); + } + + gpu->PerformMemoryDownload(colorBuffer, size); + NotifyMemInfo(MemBlockFlags::WRITE, colorBuffer, size, "godseaterburst_depthmask_5551"); + + return 0; +} + static int Hook_hexyzforce_monoclome_thread() { u32 fb_info; if (!GetMIPSStaticAddress(fb_info, -4, 0)) { @@ -1414,6 +1443,7 @@ static const ReplacementTableEntry entries[] = { // { "vmmul_q_transp", &Replace_vmmul_q_transp, 0, REPFLAG_DISABLED }, { "godseaterburst_blit_texture", &Hook_godseaterburst_blit_texture, 0, REPFLAG_HOOKENTER }, + { "godseaterburst_depthmask_5551", &Hook_godseaterburst_depthmask_5551, 0, REPFLAG_HOOKENTER }, { "hexyzforce_monoclome_thread", &Hook_hexyzforce_monoclome_thread, 0, REPFLAG_HOOKENTER, 0x58 }, { "starocean_write_stencil", &Hook_starocean_write_stencil, 0, REPFLAG_HOOKENTER, 0x260 }, { "topx_create_saveicon", &Hook_topx_create_saveicon, 0, REPFLAG_HOOKENTER, 0x34 }, diff --git a/Core/MIPS/MIPSAnalyst.cpp b/Core/MIPS/MIPSAnalyst.cpp index 81f87da66374..09e9771c34ad 100644 --- a/Core/MIPS/MIPSAnalyst.cpp +++ b/Core/MIPS/MIPSAnalyst.cpp @@ -289,6 +289,7 @@ static const HardHashTableEntry hardcodedHashes[] = { { 0x70a6152b265228e8, 296, "unendingbloodycall_download_frame", }, // unENDing Bloody Call { 0x7245b74db370ae72, 64, "vmmul_q_transp3", }, { 0x7259d52b21814a5a, 40, "vtfm_t_transp", }, + { 0x730f59cc6c0f5732, 452, "godseaterburst_depthmask_5551", }, // Gods Eater Burst (US) { 0x7354fd206796d817, 864, "flowers_download_frame", }, // Flowers { 0x736b34ebc702d873, 104, "vmmul_q_transp", }, { 0x73a614c08f777d52, 792, "danganronpa2_2_download_frame", }, // Danganronpa 2 From d0eb14ec0214788b4061cc61510c8c752791cae9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 9 Oct 2022 00:54:59 -0700 Subject: [PATCH 3/4] GPU: Correct sizing account on block transfer. --- GPU/Common/FramebufferManagerCommon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 17c618c43a4d..308bd8bfeb16 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -2605,7 +2605,7 @@ void FramebufferManagerCommon::PackFramebufferSync(VirtualFramebuffer *vfb, int const int dstByteOffset = (y * stride + x) * dstBpp; // Leave the gap between the end of the last line and the full stride. // This is only used for the NotifyMemInfo range. - const int dstSize = (h * stride + w - 1) * dstBpp; + const int dstSize = ((h - 1) * stride + w) * dstBpp; if (!Memory::IsValidRange(fb_address + dstByteOffset, dstSize)) { ERROR_LOG_REPORT(G3D, "PackFramebufferSync would write outside of memory, ignoring"); From ad3220f8572faca0d8756d65e6823f73d7d2a4c9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 9 Oct 2022 01:08:04 -0700 Subject: [PATCH 4/4] GLES: Hook up depth download. Currently, only used by one hook. --- GPU/Common/FramebufferManagerCommon.cpp | 17 ++++++++++++++++- GPU/Common/FramebufferManagerCommon.h | 2 ++ GPU/Directx9/FramebufferManagerDX9.h | 2 +- GPU/GLES/FramebufferManagerGLES.h | 3 +-- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 308bd8bfeb16..7fbb9a74fcd4 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -2619,7 +2619,11 @@ void FramebufferManagerCommon::PackFramebufferSync(VirtualFramebuffer *vfb, int DEBUG_LOG(G3D, "Reading framebuffer to mem, fb_address = %08x, ptr=%p", fb_address, destPtr); if (destPtr) { - draw_->CopyFramebufferToMemorySync(vfb->fbo, channel == RASTER_COLOR ? Draw::FB_COLOR_BIT : Draw::FB_DEPTH_BIT, x, y, w, h, destFormat, destPtr, vfb->fb_stride, "PackFramebufferSync"); + if (channel == RASTER_DEPTH) + PackDepthbuffer(vfb, x, y, w, h); + else + draw_->CopyFramebufferToMemorySync(vfb->fbo, channel == RASTER_COLOR ? Draw::FB_COLOR_BIT : Draw::FB_DEPTH_BIT, x, y, w, h, destFormat, destPtr, vfb->fb_stride, "PackFramebufferSync"); + char tag[128]; size_t len = snprintf(tag, sizeof(tag), "FramebufferPack/%08x_%08x_%dx%d_%s", vfb->fb_address, vfb->z_address, w, h, GeBufferFormatToString(vfb->fb_format)); NotifyMemInfo(MemBlockFlags::WRITE, fb_address + dstByteOffset, dstSize, tag, len); @@ -2630,6 +2634,17 @@ void FramebufferManagerCommon::PackFramebufferSync(VirtualFramebuffer *vfb, int gpuStats.numReadbacks++; } +void FramebufferManagerCommon::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h) { + _assert_msg_(vfb && vfb->z_address != 0 && vfb->z_stride != 0, "Depth buffer invalid"); + + Draw::DataFormat destFormat = GEFormatToThin3D(GE_FORMAT_DEPTH16); + const int dstByteOffset = (y * vfb->z_stride + x) * 2; + u8 *destPtr = Memory::GetPointerWriteUnchecked(vfb->z_address + dstByteOffset); + if (!draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_DEPTH_BIT, x, y, w, h, destFormat, destPtr, vfb->fb_stride, "PackDepthbuffer")) { + WARN_LOG(G3D, "PackDepthbuffer failed"); + } +} + void FramebufferManagerCommon::ReadFramebufferToMemory(VirtualFramebuffer *vfb, int x, int y, int w, int h, RasterChannel channel) { // Clamp to bufferWidth. Sometimes block transfers can cause this to hit. if (x + w >= vfb->bufferWidth) { diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index b3bd21d7c987..e727c1a25a78 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -442,6 +442,8 @@ class FramebufferManagerCommon { protected: virtual void PackFramebufferSync(VirtualFramebuffer *vfb, int x, int y, int w, int h, RasterChannel channel); + // Used for when a shader is required, such as GLES. + virtual void PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h); void SetViewport2D(int x, int y, int w, int h); Draw::Texture *MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height); void DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation, int flags); diff --git a/GPU/Directx9/FramebufferManagerDX9.h b/GPU/Directx9/FramebufferManagerDX9.h index 0f4f7d7ce1c3..1d7e522b48f1 100644 --- a/GPU/Directx9/FramebufferManagerDX9.h +++ b/GPU/Directx9/FramebufferManagerDX9.h @@ -49,10 +49,10 @@ class FramebufferManagerDX9 : public FramebufferManagerCommon { protected: void DecimateFBOs() override; + void PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h) override; private: void PackFramebufferSync(VirtualFramebuffer *vfb, int x, int y, int w, int h, RasterChannel channel) override; - void PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h); bool GetRenderTargetFramebuffer(LPDIRECT3DSURFACE9 renderTarget, LPDIRECT3DSURFACE9 offscreen, int w, int h, GPUDebugBuffer &buffer); LPDIRECT3DDEVICE9 device_; diff --git a/GPU/GLES/FramebufferManagerGLES.h b/GPU/GLES/FramebufferManagerGLES.h index eb5354b60ee9..e75de973085f 100644 --- a/GPU/GLES/FramebufferManagerGLES.h +++ b/GPU/GLES/FramebufferManagerGLES.h @@ -38,10 +38,9 @@ class FramebufferManagerGLES : public FramebufferManagerCommon { protected: void UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) override; + void PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h) override; private: - void PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h); - u8 *convBuf_ = nullptr; u32 convBufSize_ = 0;