mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-28 19:00:23 +00:00
Support render-to-clut, at least in some cases.
This is pretty much only tested with Brave Story. See #6754. There may be other cases which are not handled yet.
This commit is contained in:
parent
a7b4c38464
commit
8e2557bafe
@ -420,6 +420,7 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame
|
||||
vfb->last_frame_used = 0;
|
||||
vfb->last_frame_attached = 0;
|
||||
vfb->last_frame_displayed = 0;
|
||||
vfb->last_frame_clut = 0;
|
||||
frameLastFramebufUsed_ = gpuStats.numFlips;
|
||||
vfbs_.push_back(vfb);
|
||||
currentRenderVfb_ = vfb;
|
||||
@ -571,6 +572,13 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size,
|
||||
srcBuffer = vfb;
|
||||
srcY = yOffset;
|
||||
srcH = 1;
|
||||
} else if (yOffset == 0 && yOffset < srcY) {
|
||||
// Okay, last try - it might be a clut.
|
||||
if (vfb->usageFlags & FB_USAGE_CLUT) {
|
||||
srcBuffer = vfb;
|
||||
srcY = yOffset;
|
||||
srcH = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -664,7 +672,13 @@ void FramebufferManagerCommon::FindTransferFramebuffers(VirtualFramebuffer *&dst
|
||||
// Grand Knights History copies with a mismatching stride but a full line at a time.
|
||||
// Makes it hard to detect the wrong transfers in e.g. God of War.
|
||||
if (width != dstStride || (byteStride * height != vfb_byteStride && byteStride * height != vfb_byteWidth)) {
|
||||
match = false;
|
||||
// However, some other games write cluts to framebuffers.
|
||||
// Let's catch this and upload. Otherwise reject the match.
|
||||
match = (vfb->usageFlags & FB_USAGE_CLUT) != 0;
|
||||
if (match) {
|
||||
dstWidth = byteStride * height / vfb_bpp;
|
||||
dstHeight = 1;
|
||||
}
|
||||
} else {
|
||||
dstWidth = byteStride * height / vfb_bpp;
|
||||
dstHeight = 1;
|
||||
@ -866,6 +880,7 @@ void FramebufferManagerCommon::UpdateFramebufUsage(VirtualFramebuffer *vfb) {
|
||||
checkFlag(FB_USAGE_DISPLAYED_FRAMEBUFFER, vfb->last_frame_displayed);
|
||||
checkFlag(FB_USAGE_TEXTURE, vfb->last_frame_used);
|
||||
checkFlag(FB_USAGE_RENDERTARGET, vfb->last_frame_render);
|
||||
checkFlag(FB_USAGE_CLUT, vfb->last_frame_clut);
|
||||
}
|
||||
|
||||
void FramebufferManagerCommon::ShowScreenResolution() {
|
||||
|
@ -29,6 +29,7 @@ enum {
|
||||
FB_USAGE_DISPLAYED_FRAMEBUFFER = 1,
|
||||
FB_USAGE_RENDERTARGET = 2,
|
||||
FB_USAGE_TEXTURE = 4,
|
||||
FB_USAGE_CLUT = 8,
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -55,6 +56,7 @@ struct VirtualFramebuffer {
|
||||
int last_frame_attached;
|
||||
int last_frame_render;
|
||||
int last_frame_displayed;
|
||||
int last_frame_clut;
|
||||
bool memoryUpdated;
|
||||
bool depthUpdated;
|
||||
|
||||
|
@ -779,10 +779,27 @@ static inline u32 QuickTexHash(u32 addr, int bufw, int w, int h, GETextureFormat
|
||||
}
|
||||
|
||||
void TextureCacheDX9::LoadClut(u32 clutAddr, u32 loadBytes) {
|
||||
// Clear the uncached bit, etc. to match framebuffers.
|
||||
clutAddr = clutAddr & 0x3FFFFFFF;
|
||||
bool foundFramebuffer = false;
|
||||
|
||||
for (size_t i = 0, n = fbCache_.size(); i < n; ++i) {
|
||||
auto framebuffer = fbCache_[i];
|
||||
if ((framebuffer->fb_address | 0x04000000) == clutAddr) {
|
||||
framebuffer->last_frame_clut = gpuStats.numFlips;
|
||||
framebuffer->usageFlags |= FB_USAGE_CLUT;
|
||||
foundFramebuffer = true;
|
||||
}
|
||||
}
|
||||
|
||||
clutTotalBytes_ = loadBytes;
|
||||
if (Memory::IsValidAddress(clutAddr)) {
|
||||
// It's possible for a game to (successfully) access outside valid memory.
|
||||
u32 bytes = Memory::ValidSize(clutAddr, loadBytes);
|
||||
if (foundFramebuffer) {
|
||||
gpu->PerformMemoryDownload(clutAddr, bytes);
|
||||
}
|
||||
|
||||
#ifdef _M_SSE
|
||||
int numBlocks = bytes / 16;
|
||||
if (bytes == loadBytes) {
|
||||
|
@ -801,10 +801,27 @@ static inline u32 QuickTexHash(u32 addr, int bufw, int w, int h, GETextureFormat
|
||||
}
|
||||
|
||||
void TextureCache::LoadClut(u32 clutAddr, u32 loadBytes) {
|
||||
// Clear the uncached bit, etc. to match framebuffers.
|
||||
clutAddr = clutAddr & 0x3FFFFFFF;
|
||||
bool foundFramebuffer = false;
|
||||
|
||||
for (size_t i = 0, n = fbCache_.size(); i < n; ++i) {
|
||||
auto framebuffer = fbCache_[i];
|
||||
if ((framebuffer->fb_address | 0x04000000) == clutAddr) {
|
||||
framebuffer->last_frame_clut = gpuStats.numFlips;
|
||||
framebuffer->usageFlags |= FB_USAGE_CLUT;
|
||||
foundFramebuffer = true;
|
||||
}
|
||||
}
|
||||
|
||||
clutTotalBytes_ = loadBytes;
|
||||
if (Memory::IsValidAddress(clutAddr)) {
|
||||
// It's possible for a game to (successfully) access outside valid memory.
|
||||
u32 bytes = Memory::ValidSize(clutAddr, loadBytes);
|
||||
if (foundFramebuffer) {
|
||||
gpu->PerformMemoryDownload(clutAddr, bytes);
|
||||
}
|
||||
|
||||
#ifdef _M_SSE
|
||||
int numBlocks = bytes / 16;
|
||||
if (bytes == loadBytes) {
|
||||
|
Loading…
Reference in New Issue
Block a user