mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge pull request #16184 from unknownbrackets/depth-download
GPU: Hook Gods Eater Burst avatar read
This commit is contained in:
commit
28bc45451c
7 changed files with 88 additions and 14 deletions
|
@ -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 },
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1666,13 +1666,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;
|
||||
}
|
||||
|
||||
|
@ -1724,14 +1725,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) {
|
||||
|
@ -1749,7 +1772,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");
|
||||
}
|
||||
|
@ -1761,7 +1784,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.
|
||||
|
@ -1771,8 +1796,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;
|
||||
|
@ -2589,7 +2614,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");
|
||||
|
@ -2603,7 +2628,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);
|
||||
|
@ -2614,6 +2643,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) {
|
||||
|
@ -2632,7 +2672,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.
|
||||
|
|
|
@ -442,6 +442,8 @@ public:
|
|||
|
||||
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);
|
||||
|
|
|
@ -49,10 +49,10 @@ public:
|
|||
|
||||
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_;
|
||||
|
|
|
@ -38,10 +38,9 @@ public:
|
|||
|
||||
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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue