Skip some code if things are outside framebuffers.

Small optimization.
This commit is contained in:
Unknown W. Brackets 2014-05-25 17:01:28 -07:00
parent 4dbb4328ae
commit fd4ba0093c
3 changed files with 46 additions and 12 deletions

View File

@ -327,7 +327,8 @@ FramebufferManager::FramebufferManager() :
shaderManager_(0),
usePostShader_(false),
postShaderAtOutputResolution_(false),
resized_(false)
resized_(false),
framebufRangeEnd_(0)
#ifndef USING_GLES2
,
pixelBufObj_(0),
@ -836,6 +837,11 @@ void FramebufferManager::DoSetRenderFrameBuffer() {
glEnable(GL_DITHER); // why?
currentRenderVfb_ = vfb;
u32 byteSize = vfb->fb_stride * vfb->height * (vfb->format == GE_FORMAT_8888 ? 4 : 2);
if (fb_address + byteSize > framebufRangeEnd_) {
framebufRangeEnd_ = ((fb_address + byteSize) & 0x3FFFFFFF) | 0x04000000;
}
INFO_LOG(SCEGE, "Creating FBO for %08x : %i x %i x %i", vfb->fb_address, vfb->width, vfb->height, vfb->format);
// Let's check for depth buffer overlap. Might be interesting.
@ -1798,6 +1804,11 @@ void FramebufferManager::UpdateFromMemory(u32 addr, int size, bool safe) {
}
void FramebufferManager::NotifyFramebufferCopy(u32 src, u32 dst, int size) {
if (!MayIntersectFramebuffer(src) && !MayIntersectFramebuffer(dst)) {
// Don't waste time looking if neither can be a framebuffer.
return;
}
// MotoGP workaround
for (size_t i = 0; i < vfbs_.size(); i++) {
int bpp = vfbs_[i]->format == GE_FORMAT_8888 ? 4 : 2;
@ -1867,6 +1878,11 @@ bool FramebufferManager::NotifyBlockTransferBefore(u32 dstBasePtr, int dstStride
return false;
}
// Skip checking if there's no framebuffers in that area.
if (!MayIntersectFramebuffer(srcBasePtr) && !MayIntersectFramebuffer(dstBasePtr)) {
return false;
}
VirtualFramebuffer *dstBuffer = 0;
VirtualFramebuffer *srcBuffer = 0;
FindTransferFramebuffers(dstBuffer, srcBuffer, dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, bpp);
@ -1903,7 +1919,8 @@ void FramebufferManager::NotifyBlockTransferAfter(u32 dstBasePtr, int dstStride,
return;
}
if (Memory::IsRAMAddress(srcBasePtr) && Memory::IsVRAMAddress(dstBasePtr)) {
// TODO: This can probably just be handled by a normal block transfer upload, no?
if (Memory::IsRAMAddress(srcBasePtr) && MayIntersectFramebuffer(dstBasePtr)) {
// TODO: This causes glitches in Tactics Ogre if we don't implement both ways (which will probably be slow...)
// The main thing this helps is videos, which will have a matching stride, and zero x/y.
if (dstStride == srcStride && dstY == 0 && dstX == 0 && srcX == 0 && srcY == 0) {
@ -1917,6 +1934,7 @@ void FramebufferManager::NotifyBlockTransferAfter(u32 dstBasePtr, int dstStride,
u32 backBuffer = PrevDisplayFramebufAddr();
u32 displayBuffer = DisplayFramebufAddr();
// TODO: Is this not handled by upload? Should we check !dstBuffer to avoid a double copy?
if (((backBuffer != 0 && dstBasePtr == backBuffer) ||
(displayBuffer != 0 && dstBasePtr == displayBuffer)) &&
dstStride == 512 && height == 272) {
@ -1924,15 +1942,17 @@ void FramebufferManager::NotifyBlockTransferAfter(u32 dstBasePtr, int dstStride,
DrawFramebuffer(Memory::GetPointerUnchecked(dstBasePtr), GE_FORMAT_8888, 512, false);
}
VirtualFramebuffer *dstBuffer = 0;
VirtualFramebuffer *srcBuffer = 0;
FindTransferFramebuffers(dstBuffer, srcBuffer, dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, bpp);
if (MayIntersectFramebuffer(srcBasePtr) || MayIntersectFramebuffer(dstBasePtr)) {
VirtualFramebuffer *dstBuffer = 0;
VirtualFramebuffer *srcBuffer = 0;
FindTransferFramebuffers(dstBuffer, srcBuffer, dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, bpp);
if (dstBuffer && !srcBuffer) {
WARN_LOG_REPORT_ONCE(btu, G3D, "Block transfer upload (not supported) %08x -> %08x", srcBasePtr, dstBasePtr);
if (g_Config.bBlockTransferGPU) {
u8 *srcBase = Memory::GetPointerUnchecked(srcBasePtr) + (srcX + srcY * srcStride) * bpp;
DrawPixels(dstBuffer, dstX, dstY, srcBase, dstBuffer->format, srcStride * bpp, width, height);
if (dstBuffer && !srcBuffer) {
WARN_LOG_REPORT_ONCE(btu, G3D, "Block transfer upload (not supported) %08x -> %08x", srcBasePtr, dstBasePtr);
if (g_Config.bBlockTransferGPU) {
u8 *srcBase = Memory::GetPointerUnchecked(srcBasePtr) + (srcX + srcY * srcStride) * bpp;
DrawPixels(dstBuffer, dstX, dstY, srcBase, dstBuffer->format, srcStride * bpp, width, height);
}
}
}
}

View File

@ -200,6 +200,16 @@ public:
}
}
bool MayIntersectFramebuffer(u32 start) {
// Clear the cache/kernel bits.
start = start & 0x3FFFFFFF;
// Most games only have two framebuffers at the start.
if (start >= framebufRangeEnd_ || start < PSP_GetVidMemBase()) {
return false;
}
return true;
}
void NotifyFramebufferCopy(u32 src, u32 dest, int size);
void DestroyFramebuf(VirtualFramebuffer *vfb);
@ -261,7 +271,10 @@ private:
bool resized_;
bool useBufferedRendering_;
bool updateVRAM_;
// The range of PSP memory that may contain FBOs. So we can skip iterating.
u32 framebufRangeEnd_;
std::vector<VirtualFramebuffer *> bvfbs_; // blitting FBOs
std::map<std::pair<int, int>, FBO *> renderCopies_;

View File

@ -1955,8 +1955,9 @@ void GLES_GPU::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType t
else
textureCache_.InvalidateAll(type);
if (type != GPU_INVALIDATE_ALL)
if (type != GPU_INVALIDATE_ALL && framebufferManager_.MayIntersectFramebuffer(addr)) {
framebufferManager_.UpdateFromMemory(addr, size, type == GPU_INVALIDATE_SAFE);
}
}
void GLES_GPU::UpdateMemory(u32 dest, u32 src, int size) {