Skip to content

Commit

Permalink
Duplicate framebuffers textured onto themselves.
Browse files Browse the repository at this point in the history
This fixes hrydgard#2917.

I verified that, at least for my card, blitting is much faster than
glReadPixels (by quite a margin.)
  • Loading branch information
unknownbrackets committed Jan 20, 2014
1 parent 8eefca5 commit c01829e
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 19 deletions.
45 changes: 44 additions & 1 deletion GPU/GLES/Framebuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,8 @@ FramebufferManager::FramebufferManager() :
shaderManager_(0),
usePostShader_(false),
postShaderAtOutputResolution_(false),
resized_(false)
resized_(false),
renderCopy_(0)
#ifndef USING_GLES2
,
pixelBufObj_(0),
Expand Down Expand Up @@ -919,6 +920,48 @@ void FramebufferManager::SetLineWidth() {
#endif
}

void FramebufferManager::BindFramebufferColor(VirtualFramebuffer *framebuffer) {
if (!framebuffer->fbo || !useBufferedRendering_) {
glBindTexture(GL_TEXTURE_2D, 0);
gstate_c.skipDrawReason |= SKIPDRAW_BAD_FB_TEXTURE;
return;
}

if (MaskedEqual(framebuffer->fb_address, gstate.getFrameBufRawAddress())) {
#ifndef USING_GLES2
if (gl_extensions.FBO_ARB) {
#else
if (gl_extensions.GLES3) {
#endif
#ifdef MAY_HAVE_GLES3

// TODO: Maybe merge with bvfbs_? Not sure if those could be packing, and they're created at a different size.
if (!renderCopy_ || renderCopyWidth_ != framebuffer->renderWidth || renderCopyHeight_ != framebuffer->renderHeight) {
if (renderCopy_)
fbo_destroy(renderCopy_);
renderCopy_ = fbo_create(framebuffer->renderWidth, framebuffer->renderHeight, 1, true, framebuffer->colorDepth);
renderCopyWidth_ = framebuffer->renderWidth;
renderCopyHeight_ = framebuffer->renderHeight;
}

fbo_bind_as_render_target(renderCopy_);
glViewport(0, 0, framebuffer->renderWidth, framebuffer->renderHeight);
fbo_bind_for_read(framebuffer->fbo);
glBlitFramebuffer(0, 0, framebuffer->renderWidth, framebuffer->renderHeight, 0, 0, framebuffer->renderWidth, framebuffer->renderHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);

fbo_bind_as_render_target(currentRenderVfb_->fbo);
if (gl_extensions.gpuVendor != GPU_VENDOR_POWERVR)
glstate.viewport.restore();
fbo_bind_color_as_texture(renderCopy_, 0);
#endif
} else {
fbo_bind_color_as_texture(framebuffer->fbo, 0);
}
} else {
fbo_bind_color_as_texture(framebuffer->fbo, 0);
}
}

void FramebufferManager::CopyDisplayToOutput() {
fbo_unbind();
glstate.viewport.set(0, 0, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight);
Expand Down
6 changes: 6 additions & 0 deletions GPU/GLES/Framebuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ class FramebufferManager {
void UpdateFromMemory(u32 addr, int size, bool safe);
void SetLineWidth();

// For use when texturing from a framebuffer. May create a duplicate if target.
void BindFramebufferColor(VirtualFramebuffer *framebuffer);

#ifdef USING_GLES2
void ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool sync = true);
#else
Expand Down Expand Up @@ -223,6 +226,9 @@ class FramebufferManager {
bool useBufferedRendering_;

std::vector<VirtualFramebuffer *> bvfbs_; // blitting FBOs
FBO *renderCopy_;
int renderCopyWidth_;
int renderCopyHeight_;

std::set<std::pair<u32, u32>> knownFramebufferCopies_;

Expand Down
1 change: 1 addition & 0 deletions GPU/GLES/GLES_GPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,7 @@ GLES_GPU::GLES_GPU()
transformDraw_.SetFramebufferManager(&framebufferManager_);
framebufferManager_.SetTextureCache(&textureCache_);
framebufferManager_.SetShaderManager(shaderManager_);
textureCache_.SetFramebufferManager(&framebufferManager_);

// Sanity check gstate
if ((int *)&gstate.transferstart - (int *)&gstate != 0xEA) {
Expand Down
24 changes: 6 additions & 18 deletions GPU/GLES/TextureCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -830,22 +830,15 @@ bool SetDebugTexture() {
}
#endif

void TextureCache::SetTextureFramebuffer(TexCacheEntry *entry)
{
void TextureCache::SetTextureFramebuffer(TexCacheEntry *entry) {
entry->framebuffer->usageFlags |= FB_USAGE_TEXTURE;
bool useBufferedRendering = g_Config.iRenderingMode != FB_NON_BUFFERED_MODE;
if (useBufferedRendering) {
// For now, let's not bind FBOs that we know are off (invalidHint will be -1.)
// But let's still not use random memory.
if (entry->framebuffer->fbo) {
fbo_bind_color_as_texture(entry->framebuffer->fbo, 0);
// Keep the framebuffer alive.
// TODO: Dangerous if it sets a new one?
entry->framebuffer->last_frame_used = gpuStats.numFlips;
} else {
glBindTexture(GL_TEXTURE_2D, 0);
gstate_c.skipDrawReason |= SKIPDRAW_BAD_FB_TEXTURE;
}
framebufferManager_->BindFramebufferColor(entry->framebuffer);

// Keep the framebuffer alive.
entry->framebuffer->last_frame_used = gpuStats.numFlips;

// We need to force it, since we may have set it on a texture before attaching.
UpdateSamplingParams(*entry, true);
gstate_c.curTextureWidth = entry->framebuffer->width;
Expand Down Expand Up @@ -883,11 +876,6 @@ void TextureCache::SetTexture(bool force) {
int w = gstate.getTextureWidth(0);
int h = gstate.getTextureHeight(0);

u32 fb_addr = gstate.getFrameBufRawAddress() | 0x04000000;
if (fb_addr == gstate.getTextureAddress(0)) {
WARN_LOG_REPORT(HLE, "Texturing from same buffer as target (%08x : %ix%i)", fb_addr, w, h);
}

GETextureFormat format = gstate.getTextureFormat();
if (format >= 11) {
ERROR_LOG_REPORT(G3D, "Unknown texture format %i", format);
Expand Down
6 changes: 6 additions & 0 deletions GPU/GLES/TextureCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "TextureScaler.h"

struct VirtualFramebuffer;
class FramebufferManager;

enum TextureFiltering {
AUTO = 1,
Expand Down Expand Up @@ -56,6 +57,10 @@ class TextureCache {
// are being rendered to. This is barebones so far.
void NotifyFramebuffer(u32 address, VirtualFramebuffer *framebuffer, FramebufferNotification msg);

void SetFramebufferManager(FramebufferManager *fbManager) {
framebufferManager_ = fbManager;
}

size_t NumLoadedTextures() const {
return cache.size();
}
Expand Down Expand Up @@ -160,5 +165,6 @@ class TextureCache {
float maxAnisotropyLevel;

int decimationCounter_;
FramebufferManager *framebufferManager_;
};

0 comments on commit c01829e

Please sign in to comment.