mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-25 09:09:49 +00:00
Merge pull request #7591 from unknownbrackets/gpu-framebuf
Better glInvalidateFramebuffer usage, track usage flags better
This commit is contained in:
commit
085ecc0a64
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
};
|
||||
};
|
||||
|
@ -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(); ) {
|
||||
|
@ -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(); ) {
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user