Merge pull request #7591 from unknownbrackets/gpu-framebuf

Better glInvalidateFramebuffer usage, track usage flags better
This commit is contained in:
Henrik Rydgård 2015-03-15 11:18:30 +01:00
commit 085ecc0a64
5 changed files with 73 additions and 21 deletions

View File

@ -333,6 +333,7 @@ void FramebufferManagerCommon::DoSetRenderFrameBuffer() {
vfb->last_frame_render = gpuStats.numFlips;
vfb->last_frame_used = 0;
vfb->last_frame_attached = 0;
vfb->last_frame_displayed = 0;
frameLastFramebufUsed_ = gpuStats.numFlips;
vfbs_.push_back(vfb);
currentRenderVfb_ = vfb;
@ -765,4 +766,19 @@ void FramebufferManagerCommon::SetRenderSize(VirtualFramebuffer *vfb) {
vfb->renderWidth = (u16)(vfb->bufferWidth * renderWidthFactor);
vfb->renderHeight = (u16)(vfb->bufferHeight * renderHeightFactor);
}
}
}
void FramebufferManagerCommon::UpdateFramebufUsage(VirtualFramebuffer *vfb) {
auto checkFlag = [&](u16 flag, int last_frame) {
if (vfb->usageFlags & flag) {
const int age = frameLastFramebufUsed_ - last_frame;
if (age > FBO_OLD_USAGE_FLAG) {
vfb->usageFlags &= ~flag;
}
}
};
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);
}

View File

@ -50,6 +50,7 @@ struct VirtualFramebuffer {
int last_frame_used;
int last_frame_attached;
int last_frame_render;
int last_frame_displayed;
bool memoryUpdated;
bool depthUpdated;
@ -195,6 +196,8 @@ protected:
bool ShouldDownloadFramebuffer(const VirtualFramebuffer *vfb) const;
void FindTransferFramebuffers(VirtualFramebuffer *&dstBuffer, VirtualFramebuffer *&srcBuffer, u32 dstBasePtr, int dstStride, int &dstX, int &dstY, u32 srcBasePtr, int srcStride, int &srcX, int &srcY, int &srcWidth, int &srcHeight, int &dstWidth, int &dstHeight, int bpp) const;
void UpdateFramebufUsage(VirtualFramebuffer *vfb);
void SetColorUpdated(VirtualFramebuffer *dstBuffer) {
dstBuffer->memoryUpdated = false;
dstBuffer->dirtyAfterDisplay = true;
@ -230,5 +233,6 @@ protected:
// Aggressively delete unused FBOs to save gpu memory.
enum {
FBO_OLD_AGE = 5,
FBO_OLD_USAGE_FLAG = 15,
};
};

View File

@ -732,6 +732,7 @@ namespace DX9 {
}
vfb->usageFlags |= FB_USAGE_DISPLAYED_FRAMEBUFFER;
vfb->last_frame_displayed = gpuStats.numFlips;
vfb->dirtyAfterDisplay = false;
vfb->reallyDirtyAfterDisplay = false;
@ -756,9 +757,6 @@ namespace DX9 {
float x, y, w, h;
CenterRect(&x, &y, &w, &h, 480.0f, 272.0f, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight);
// TODO ES3: Use glInvalidateFramebuffer to discard depth/stencil data at the end of frame.
// and to discard extraFBOs_ after using them.
const float u0 = offsetX / (float)vfb->bufferWidth;
const float v0 = offsetY / (float)vfb->bufferHeight;
const float u1 = (480.0f + offsetX) / (float)vfb->bufferWidth;
@ -1152,15 +1150,16 @@ namespace DX9 {
ReadFramebufferToMemory(vfb, false, 0, 0, vfb->width, vfb->height);
}
if (vfb == displayFramebuf_ || vfb == prevDisplayFramebuf_ || vfb == prevPrevDisplayFramebuf_) {
continue;
if (vfb != displayFramebuf_ && vfb != prevDisplayFramebuf_ && vfb != prevPrevDisplayFramebuf_) {
if (age > FBO_OLD_AGE) {
INFO_LOG(SCEGE, "Decimating FBO for %08x (%i x %i x %i), age %i", vfb->fb_address, vfb->width, vfb->height, vfb->format, age);
DestroyFramebuf(vfb);
vfbs_.erase(vfbs_.begin() + i--);
}
}
if (age > FBO_OLD_AGE) {
INFO_LOG(SCEGE, "Decimating FBO for %08x (%i x %i x %i), age %i", vfb->fb_address, vfb->width, vfb->height, vfb->format, age);
DestroyFramebuf(vfb);
vfbs_.erase(vfbs_.begin() + i--);
}
// Let's also "decimate" the usageFlags.
UpdateFramebufUsage(vfb);
}
for (auto it = tempFBOs_.begin(); it != tempFBOs_.end(); ) {

View File

@ -1086,6 +1086,7 @@ void FramebufferManager::CopyDisplayToOutput() {
}
vfb->usageFlags |= FB_USAGE_DISPLAYED_FRAMEBUFFER;
vfb->last_frame_displayed = gpuStats.numFlips;
vfb->dirtyAfterDisplay = false;
vfb->reallyDirtyAfterDisplay = false;
@ -1114,7 +1115,6 @@ void FramebufferManager::CopyDisplayToOutput() {
CenterRect(&x, &y, &w, &h, 480.0f, 272.0f, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight);
// TODO ES3: Use glInvalidateFramebuffer to discard depth/stencil data at the end of frame.
// and to discard extraFBOs_ after using them.
const float u0 = offsetX / (float)vfb->bufferWidth;
const float v0 = offsetY / (float)vfb->bufferHeight;
@ -1166,6 +1166,12 @@ void FramebufferManager::CopyDisplayToOutput() {
glstate.viewport.set(0, 0, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight);
DrawActiveTexture(colorTexture, x, y, w, h, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight, true, u0, v0, u1, v1);
}
if (gl_extensions.GLES3 && glInvalidateFramebuffer != nullptr) {
fbo_bind_as_render_target(extraFBOs_[0]);
GLenum attachments[3] = { GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT };
glInvalidateFramebuffer(GL_FRAMEBUFFER, 3, attachments);
}
} else {
if (g_Config.bEnableCardboard) {
// Left Eye Image
@ -1756,6 +1762,18 @@ void FramebufferManager::PackFramebufferSync_(VirtualFramebuffer *vfb, int x, in
}
}
if (gl_extensions.GLES3 && glInvalidateFramebuffer != nullptr) {
#ifdef USING_GLES2
// GLES3 doesn't support using GL_READ_FRAMEBUFFER here.
fbo_bind_as_render_target(vfb->fbo);
const GLenum target = GL_FRAMEBUFFER;
#else
const GLenum target = GL_READ_FRAMEBUFFER;
#endif
GLenum attachments[3] = { GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT };
glInvalidateFramebuffer(target, 3, attachments);
}
fbo_unbind_read();
}
@ -1778,6 +1796,20 @@ void FramebufferManager::EndFrame() {
if (updateVRAM_)
PackFramebufferAsync_(NULL);
#endif
// Let's explicitly invalidate any temp FBOs used during this frame.
if (gl_extensions.GLES3 && glInvalidateFramebuffer != nullptr) {
for (auto temp : tempFBOs_) {
if (temp.second.last_frame_used < gpuStats.numFlips) {
continue;
}
fbo_bind_as_render_target(temp.second.fbo);
GLenum attachments[3] = { GL_COLOR_ATTACHMENT0, GL_STENCIL_ATTACHMENT, GL_DEPTH_ATTACHMENT };
glInvalidateFramebuffer(GL_FRAMEBUFFER, 3, attachments);
}
fbo_unbind();
}
}
void FramebufferManager::DeviceLost() {
@ -1822,15 +1854,16 @@ void FramebufferManager::DecimateFBOs() {
ReadFramebufferToMemory(vfb, sync, 0, 0, vfb->width, vfb->height);
}
if (vfb == displayFramebuf_ || vfb == prevDisplayFramebuf_ || vfb == prevPrevDisplayFramebuf_) {
continue;
if (vfb != displayFramebuf_ && vfb != prevDisplayFramebuf_ && vfb != prevPrevDisplayFramebuf_) {
if (age > FBO_OLD_AGE) {
INFO_LOG(SCEGE, "Decimating FBO for %08x (%i x %i x %i), age %i", vfb->fb_address, vfb->width, vfb->height, vfb->format, age);
DestroyFramebuf(vfb);
vfbs_.erase(vfbs_.begin() + i--);
}
}
if (age > FBO_OLD_AGE) {
INFO_LOG(SCEGE, "Decimating FBO for %08x (%i x %i x %i), age %i", vfb->fb_address, vfb->width, vfb->height, vfb->format, age);
DestroyFramebuf(vfb);
vfbs_.erase(vfbs_.begin() + i--);
}
// Let's also "decimate" the usageFlags.
UpdateFramebufUsage(vfb);
}
for (auto it = tempFBOs_.begin(); it != tempFBOs_.end(); ) {

View File

@ -851,8 +851,8 @@ void EmuScreen::render() {
#ifdef USING_GLES2
// We have no use for backbuffer depth or stencil, so let tiled renderers discard them after tiling.
if (gl_extensions.GLES3 && glInvalidateFramebuffer != nullptr) {
GLenum attachments[3] = { GL_DEPTH, GL_STENCIL };
glInvalidateFramebuffer(GL_FRAMEBUFFER, 3, attachments);
GLenum attachments[2] = { GL_DEPTH, GL_STENCIL };
glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
} else if (!gl_extensions.GLES3) {
// Tiled renderers like PowerVR should benefit greatly from this. However - seems I can't call it?
bool hasDiscard = gl_extensions.EXT_discard_framebuffer; // TODO