Some work toward better FBO handling. Fixes some things, breaks some things..

This commit is contained in:
Henrik Rydgard 2013-02-21 21:37:19 +01:00
parent 7995d1418c
commit 28979e9250
8 changed files with 63 additions and 53 deletions

View file

@ -235,7 +235,7 @@ void FramebufferManager::DrawActiveTexture(float x, float y, float w, float h, b
glsl_unbind();
}
FramebufferManager::VirtualFramebuffer *FramebufferManager::GetDisplayFBO() {
VirtualFramebuffer *FramebufferManager::GetDisplayFBO() {
for (auto iter = vfbs_.begin(); iter != vfbs_.end(); ++iter) {
VirtualFramebuffer *v = *iter;
if (MaskedEqual(v->fb_address, displayFramebufPtr_) && v->format == displayFormat_) {
@ -325,6 +325,7 @@ void FramebufferManager::SetRenderFrameBuffer() {
vfb->renderWidth = (u16)(drawing_width * renderWidthFactor);
vfb->renderHeight = (u16)(drawing_height * renderHeightFactor);
vfb->format = fmt;
vfb->usageFlags = FB_USAGE_RENDERTARGET;
switch (fmt) {
case GE_FORMAT_4444: vfb->colorDepth = FBO_4444; break;
@ -342,7 +343,7 @@ void FramebufferManager::SetRenderFrameBuffer() {
//#endif
vfb->fbo = fbo_create(vfb->renderWidth, vfb->renderHeight, 1, true, vfb->colorDepth);
textureCache_->NotifyFramebuffer(vfb->fb_address, vfb->fbo);
textureCache_->NotifyFramebuffer(vfb->fb_address, vfb);
vfb->last_frame_used = gpuStats.numFrames;
vfbs_.push_back(vfb);
@ -368,7 +369,7 @@ void FramebufferManager::SetRenderFrameBuffer() {
fbo_bind_as_render_target(vfb->fbo);
textureCache_->NotifyFramebuffer(vfb->fb_address, vfb->fbo);
textureCache_->NotifyFramebuffer(vfb->fb_address, vfb);
#ifdef USING_GLES2
// Some tiled mobile GPUs benefit IMMENSELY from clearing an FBO before rendering
// to it. This broke stuff before, so now it only clears on the first use of an
@ -482,7 +483,7 @@ void FramebufferManager::DecimateFBOs() {
}
if ((*iter)->last_frame_used + FBO_OLD_AGE < gpuStats.numFrames) {
INFO_LOG(HLE, "Destroying FBO for %08x (%i x %i x %i)", vfb->fb_address, vfb->width, vfb->height, vfb->format)
textureCache_->NotifyFramebufferDestroyed(vfb->fb_address, vfb->fbo);
textureCache_->NotifyFramebufferDestroyed(vfb->fb_address, vfb);
fbo_destroy(vfb->fbo);
delete vfb;
vfbs_.erase(iter++);
@ -495,7 +496,7 @@ void FramebufferManager::DecimateFBOs() {
void FramebufferManager::DestroyAllFBOs() {
for (auto iter = vfbs_.begin(); iter != vfbs_.end(); ++iter) {
VirtualFramebuffer *vfb = *iter;
textureCache_->NotifyFramebufferDestroyed(vfb->fb_address, vfb->fbo);
textureCache_->NotifyFramebufferDestroyed(vfb->fb_address, vfb);
fbo_destroy(vfb->fbo);
delete vfb;
}

View file

@ -38,6 +38,34 @@ enum PspDisplayPixelFormat {
PSP_DISPLAY_PIXEL_FORMAT_8888 = 3,
};
enum {
FB_USAGE_RENDERTARGET = 1,
FB_USAGE_TEXTURE = 2,
};
struct VirtualFramebuffer {
int last_frame_used;
u32 fb_address;
u32 z_address;
int fb_stride;
int z_stride;
// There's also a top left of the drawing region, but meh...
u16 width;
u16 height;
u16 renderWidth;
u16 renderHeight;
u16 usageFlags;
int format; // virtual, right now they are all RGBA8888
FBOColorDepth colorDepth;
FBO *fbo;
};
class FramebufferManager {
public:
FramebufferManager();
@ -47,25 +75,6 @@ public:
textureCache_ = tc;
}
struct VirtualFramebuffer {
int last_frame_used;
u32 fb_address;
u32 z_address;
int fb_stride;
int z_stride;
// There's also a top left of the drawing region, but meh...
u16 width;
u16 height;
u16 renderWidth;
u16 renderHeight;
int format; // virtual, right now they are all RGBA8888
FBOColorDepth colorDepth;
FBO *fbo;
};
void DrawPixels(const u8 *framebuf, int pixelFormat, int linesize);
void DrawActiveTexture(float x, float y, float w, float h, bool flip = false);

View file

@ -243,7 +243,7 @@ void LinkedShader::updateUniforms() {
if (u_proj_through != -1 && (dirtyUniforms & DIRTY_PROJTHROUGHMATRIX))
{
Matrix4x4 proj_through;
proj_through.setOrtho(0.0f, 480, 272, 0, 1, 0);
proj_through.setOrtho(0.0f, 480, 272, 0, 0, 1);
glUniformMatrix4fv(u_proj_through, 1, GL_FALSE, proj_through.getReadPtr());
}
if (u_texenv != -1 && (dirtyUniforms & DIRTY_TEXENV)) {

View file

@ -236,7 +236,7 @@ void TransformDrawEngine::UpdateViewportAndProjection() {
if (throughmode) {
// No viewport transform here. Let's experiment with using region.
glstate.viewport.set((0 + regionX1) * renderWidthFactor, (0 - regionY1) * renderHeightFactor, (regionX2 - regionX1) * renderWidthFactor, (regionY2 - regionY1) * renderHeightFactor);
glstate.depthRange.set(1.0, 0.0);
glstate.depthRange.set(0.0, 1.0);
} else {
// These we can turn into a glViewport call, offset by offsetX and offsetY. Math after.
float vpXa = getFloat24(gstate.viewportx1);

View file

@ -18,11 +18,12 @@
#include <map>
#include <algorithm>
#include "../../Core/MemMap.h"
#include "../ge_constants.h"
#include "../GPUState.h"
#include "TextureCache.h"
#include "../Core/Config.h"
#include "Core/MemMap.h"
#include "GPU/ge_constants.h"
#include "GPU/GPUState.h"
#include "GPU/GLES/TextureCache.h"
#include "GPU/GLES/Framebuffer.h"
#include "Core/Config.h"
// If a texture hasn't been seen for this many frames, get rid of it.
#define TEXTURE_KILL_AGE 200
@ -131,21 +132,21 @@ TextureCache::TexCacheEntry *TextureCache::GetEntryAt(u32 texaddr) {
return 0;
}
void TextureCache::NotifyFramebuffer(u32 address, FBO *fbo) {
void TextureCache::NotifyFramebuffer(u32 address, VirtualFramebuffer *framebuffer) {
// Must be in VRAM so | 0x04000000 it is.
TexCacheEntry *entry = GetEntryAt(address | 0x04000000);
if (entry) {
DEBUG_LOG(HLE, "Render to texture detected at %08x!", address);
if (!entry->fbo)
entry->fbo = fbo;
if (!entry->framebuffer)
entry->framebuffer= framebuffer;
// TODO: Delete the original non-fbo texture too.
}
}
void TextureCache::NotifyFramebufferDestroyed(u32 address, FBO *fbo) {
void TextureCache::NotifyFramebufferDestroyed(u32 address, VirtualFramebuffer *fbo) {
TexCacheEntry *entry = GetEntryAt(address | 0x04000000);
if (entry && entry->fbo) {
entry->fbo = 0;
if (entry && entry->framebuffer) {
entry->framebuffer = 0;
}
}
@ -699,19 +700,15 @@ void TextureCache::SetTexture() {
if (iter != cache.end()) {
entry = &iter->second;
// Check for FBO - slow!
if (entry->fbo) {
int w = 1 << (gstate.texsize[0] & 0xf);
int h = 1 << ((gstate.texsize[0] >> 8) & 0xf);
fbo_bind_color_as_texture(entry->fbo, 0);
if (entry->framebuffer) {
fbo_bind_color_as_texture(entry->framebuffer->fbo, 0);
UpdateSamplingParams(*entry, false);
int fbow, fboh;
fbo_get_dimensions(entry->fbo, &fbow, &fboh);
// This isn't right.
gstate_c.curTextureWidth = w; //w; //RoundUpToPowerOf2(fbow);
gstate_c.curTextureHeight = h; // RoundUpToPowerOf2(fboh);
gstate_c.curTextureWidth = entry->framebuffer->width;
gstate_c.curTextureHeight = entry->framebuffer->height;
int h = 1 << ((gstate.texsize[0] >> 8) & 0xf);
gstate_c.actualTextureHeight = h;
gstate_c.flipTexture = true;
entry->lastFrame = gpuStats.numFrames;
return;
@ -807,7 +804,7 @@ void TextureCache::SetTexture() {
entry->hash = texhash;
entry->format = format;
entry->lastFrame = gpuStats.numFrames;
entry->fbo = 0;
entry->framebuffer = 0;
entry->maxLevel = maxLevel;
entry->lodBias = 0.0f;

View file

@ -21,6 +21,8 @@
#include "gfx_es2/fbo.h"
#include "GPU/GPUState.h"
struct VirtualFramebuffer;
class TextureCache
{
public:
@ -36,16 +38,16 @@ public:
// FramebufferManager keeps TextureCache updated about what regions of memory
// are being rendered to. This is barebones so far.
void NotifyFramebuffer(u32 address, FBO *fbo);
void NotifyFramebufferDestroyed(u32 address, FBO *fbo);
void NotifyFramebuffer(u32 address, VirtualFramebuffer *framebuffer);
void NotifyFramebufferDestroyed(u32 address, VirtualFramebuffer *framebuffer);
size_t NumLoadedTextures() const {
return cache.size();
}
bool DecodeTexture(u8 *output, GPUgstate state);
private:
struct TexCacheEntry {
// After marking STATUS_UNRELIABLE, if it stays the same this many frames we'll trust it again.
const static int FRAMES_REGAIN_TRUST = 1000;
@ -60,7 +62,7 @@ private:
int status;
u32 addr;
u32 hash;
FBO *fbo; // if null, not sourced from an FBO.
VirtualFramebuffer *framebuffer; // if null, not sourced from an FBO.
u32 sizeInRAM;
int lastFrame;
int numFrames;

View file

@ -640,7 +640,7 @@ void TransformDrawEngine::SoftwareTransformAndDraw(
transformed[index].fog = fogCoef;
memcpy(&transformed[index].u, uv, 2 * sizeof(float));
if (gstate_c.flipTexture)
transformed[index].v = 1.0f - transformed[index].v * 2.0f;
transformed[index].v = 1.0f - transformed[index].v; //(float)gstate_c.actualTextureHeight / gstate_c.curTextureHeight - transformed[index].v;
for (int i = 0; i < 4; i++) {
transformed[index].color0[i] = c0[i] * 255.0f;
}

View file

@ -255,6 +255,7 @@ struct GPUStateCache
u32 curTextureWidth;
u32 curTextureHeight;
u32 actualTextureHeight;
float vpWidth;
float vpHeight;