mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Split the framebuffer in Killzone, with a compatibility flag.
Greatly improves performance. See issue #6207
This commit is contained in:
parent
daa62beb39
commit
987bfc79ef
8 changed files with 56 additions and 21 deletions
|
@ -96,6 +96,7 @@ void Compatibility::CheckSettings(IniFile &iniFile, const std::string &gameID) {
|
|||
CheckSetting(iniFile, gameID, "AllowLargeFBTextureOffsets", &flags_.AllowLargeFBTextureOffsets);
|
||||
CheckSetting(iniFile, gameID, "AtracLoopHack", &flags_.AtracLoopHack);
|
||||
CheckSetting(iniFile, gameID, "DeswizzleDepth", &flags_.DeswizzleDepth);
|
||||
CheckSetting(iniFile, gameID, "SplitFramebufferMargin", &flags_.SplitFramebufferMargin);
|
||||
}
|
||||
|
||||
void Compatibility::CheckSetting(IniFile &iniFile, const std::string &gameID, const char *option, bool *flag) {
|
||||
|
|
|
@ -86,6 +86,7 @@ struct CompatFlags {
|
|||
bool AllowLargeFBTextureOffsets;
|
||||
bool AtracLoopHack;
|
||||
bool DeswizzleDepth;
|
||||
bool SplitFramebufferMargin;
|
||||
};
|
||||
|
||||
class IniFile;
|
||||
|
|
|
@ -341,7 +341,7 @@ void GetFramebufferHeuristicInputs(FramebufferHeuristicParams *params, const GPU
|
|||
}
|
||||
}
|
||||
|
||||
VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const FramebufferHeuristicParams ¶ms, u32 skipDrawReason) {
|
||||
VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(FramebufferHeuristicParams ¶ms, u32 skipDrawReason) {
|
||||
gstate_c.Clean(DIRTY_FRAMEBUF);
|
||||
|
||||
// Collect all parameters. This whole function has really become a cesspool of heuristics...
|
||||
|
@ -360,6 +360,19 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame
|
|||
WARN_LOG_ONCE(color_equal_z, G3D, "Framebuffer bound with color addr == z addr, likely will not use Z in this pass: %08x", params.fb_address);
|
||||
}
|
||||
|
||||
if (PSP_CoreParameter().compat.flags().SplitFramebufferMargin && params.fb_format == GE_FORMAT_8888) {
|
||||
// Detect whether we're rendering to the margin.
|
||||
if (params.scissorWidth == 32 || params.scissorWidth == 512) {
|
||||
gstate_c.SetCurRTOffset(-480, 0);
|
||||
// Modify the fb_address and z_address too to avoid matching below.
|
||||
params.fb_address += 480 * 4;
|
||||
params.z_address += 480 * 2;
|
||||
drawing_width = 32;
|
||||
} else if (params.scissorWidth == 480) {
|
||||
drawing_width = 480;
|
||||
}
|
||||
}
|
||||
|
||||
// Find a matching framebuffer.
|
||||
VirtualFramebuffer *vfb = nullptr;
|
||||
for (auto v : vfbs_) {
|
||||
|
@ -385,7 +398,7 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame
|
|||
vfb->height = drawing_height;
|
||||
}
|
||||
break;
|
||||
} else if (v->fb_stride == params.fb_stride && v->fb_format == params.fb_format) {
|
||||
} else if (v->fb_stride == params.fb_stride && v->fb_format == params.fb_format && !PSP_CoreParameter().compat.flags().SplitFramebufferMargin) {
|
||||
u32 v_fb_first_line_end_ptr = v->fb_address + v->fb_stride * bpp;
|
||||
u32 v_fb_end_ptr = v->fb_address + v->fb_stride * v->height * bpp;
|
||||
|
||||
|
|
|
@ -279,7 +279,7 @@ public:
|
|||
void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format);
|
||||
void DestroyFramebuf(VirtualFramebuffer *v);
|
||||
|
||||
VirtualFramebuffer *DoSetRenderFrameBuffer(const FramebufferHeuristicParams ¶ms, u32 skipDrawReason);
|
||||
VirtualFramebuffer *DoSetRenderFrameBuffer(FramebufferHeuristicParams ¶ms, u32 skipDrawReason);
|
||||
VirtualFramebuffer *SetRenderFrameBuffer(bool framebufChanged, int skipDrawReason) {
|
||||
// Inlining this part since it's so frequent.
|
||||
if (!framebufChanged && currentRenderVfb_) {
|
||||
|
|
|
@ -636,16 +636,18 @@ std::vector<AttachCandidate> TextureCacheCommon::GetFramebufferCandidates(const
|
|||
}
|
||||
|
||||
if (candidates.size() > 1) {
|
||||
std::string cands;
|
||||
for (auto &candidate : candidates) {
|
||||
cands += candidate.ToString() + "\n";
|
||||
}
|
||||
if (Reporting::ShouldLogNTimes("multifbcandidate", 5)) {
|
||||
std::string cands;
|
||||
for (auto &candidate : candidates) {
|
||||
cands += candidate.ToString() + "\n";
|
||||
}
|
||||
|
||||
WARN_LOG_REPORT_ONCE(multifbcandidate, G3D, "GetFramebufferCandidates: Multiple (%d) candidate framebuffers. texaddr: %08x offset: %d (%dx%d stride %d, %s):\n%s",
|
||||
(int)candidates.size(),
|
||||
entry.addr, texAddrOffset, dimWidth(entry.dim), dimHeight(entry.dim), entry.bufw, GeTextureFormatToString(entry.format),
|
||||
cands.c_str()
|
||||
);
|
||||
WARN_LOG_N_TIMES(multifbcandidate, 5, G3D, "GetFramebufferCandidates: Multiple (%d) candidate framebuffers. texaddr: %08x offset: %d (%dx%d stride %d, %s):\n%s",
|
||||
(int)candidates.size(),
|
||||
entry.addr, texAddrOffset, dimWidth(entry.dim), dimHeight(entry.dim), entry.bufw, GeTextureFormatToString(entry.format),
|
||||
cands.c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return candidates;
|
||||
|
@ -675,6 +677,10 @@ int TextureCacheCommon::GetBestCandidateIndex(const std::vector<AttachCandidate>
|
|||
relevancy -= 2;
|
||||
}
|
||||
|
||||
if (candidate.fb == framebufferManager_->GetCurrentRenderVFB()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (relevancy > bestRelevancy) {
|
||||
bestRelevancy = relevancy;
|
||||
bestIndex = i;
|
||||
|
@ -928,12 +934,17 @@ bool TextureCacheCommon::MatchFramebuffer(
|
|||
(fb_format == GE_FORMAT_8888 && entry.format == GE_TFMT_CLUT32) ||
|
||||
(fb_format != GE_FORMAT_8888 && entry.format == GE_TFMT_CLUT16);
|
||||
|
||||
const u32 bitOffset = (texaddr - addr) * 8;
|
||||
const int bitOffset = (texaddr - addr) * 8;
|
||||
if (bitOffset != 0) {
|
||||
const u32 pixelOffset = bitOffset / std::max(1U, (u32)textureBitsPerPixel[entry.format]);
|
||||
const int pixelOffset = bitOffset / (int)std::max(1U, (u32)textureBitsPerPixel[entry.format]);
|
||||
|
||||
matchInfo->yOffset = entry.bufw == 0 ? 0 : pixelOffset / entry.bufw;
|
||||
matchInfo->xOffset = entry.bufw == 0 ? 0 : pixelOffset % entry.bufw;
|
||||
if (pixelOffset > 0) {
|
||||
matchInfo->yOffset = entry.bufw == 0 ? 0 : pixelOffset / (int)entry.bufw;
|
||||
matchInfo->xOffset = entry.bufw == 0 ? 0 : pixelOffset % (int)entry.bufw;
|
||||
} else if (pixelOffset < 0) {
|
||||
matchInfo->yOffset = entry.bufw == 0 ? 0 : pixelOffset / (int)entry.bufw;
|
||||
matchInfo->xOffset = entry.bufw == 0 ? 0 : -(-pixelOffset % (int)entry.bufw);
|
||||
}
|
||||
}
|
||||
|
||||
if (matchInfo->yOffset + minSubareaHeight >= framebuffer->height) {
|
||||
|
|
|
@ -209,8 +209,8 @@ typedef std::map<u64, std::unique_ptr<TexCacheEntry>> TexCache;
|
|||
#endif
|
||||
|
||||
struct FramebufferMatchInfo {
|
||||
u32 xOffset;
|
||||
u32 yOffset;
|
||||
int xOffset;
|
||||
int yOffset;
|
||||
bool reinterpret;
|
||||
GEBufferFormat reinterpretTo;
|
||||
};
|
||||
|
|
|
@ -621,15 +621,15 @@ struct GPUStateCache {
|
|||
u32 curRTRenderWidth;
|
||||
u32 curRTRenderHeight;
|
||||
|
||||
void SetCurRTOffset(u32 xoff, u32 yoff) {
|
||||
void SetCurRTOffset(int xoff, int yoff) {
|
||||
if (xoff != curRTOffsetX || yoff != curRTOffsetY) {
|
||||
curRTOffsetX = xoff;
|
||||
curRTOffsetY = yoff;
|
||||
Dirty(DIRTY_VIEWPORTSCISSOR_STATE);
|
||||
}
|
||||
}
|
||||
u32 curRTOffsetX;
|
||||
u32 curRTOffsetY;
|
||||
int curRTOffsetX;
|
||||
int curRTOffsetY;
|
||||
|
||||
// Set if we are doing hardware bezier/spline.
|
||||
SubmitType submitType;
|
||||
|
|
|
@ -1256,3 +1256,12 @@ UCKS45048 = true
|
|||
UCJS18030 = true
|
||||
UCJS18047 = true
|
||||
NPJG00015 = true
|
||||
|
||||
[SplitFramebufferMargin]
|
||||
# Killzone: Liberation (see issue #6207)
|
||||
UCES00279 = true
|
||||
UCKS45041 = true
|
||||
UCUS98646 = true
|
||||
UCET00278 = true
|
||||
UCUS98670 = true
|
||||
UCUS98646 = true
|
||||
|
|
Loading…
Add table
Reference in a new issue