Delete old textures, to prevent memory usage from growing indefinitely.

This commit is contained in:
Henrik Rydgard 2012-11-22 23:07:15 +01:00
parent 272bce83d6
commit d141d205f8
7 changed files with 85 additions and 19 deletions

View File

@ -47,6 +47,7 @@ public:
bool bShowAnalogStick;
bool bShowFPSCounter;
bool bShowDebugStats;
int iWindowZoom; // for Windows

View File

@ -35,6 +35,7 @@
// TODO: This file should not depend directly on GLES code.
#include "../../GPU/GLES/Framebuffer.h"
#include "../../GPU/GLES/ShaderManager.h"
#include "../../GPU/GLES/TextureCache.h"
#include "../../GPU/GPUState.h"
#include "../../GPU/GPUInterface.h"
// Internal drawing library
@ -87,6 +88,7 @@ void hleLeaveVblank(u64 userdata, int cyclesLate);
void __DisplayInit()
{
gpuStats.reset();
hasSetMode = false;
framebufIsLatched = false;
framebuf.topaddr = 0x04000000;
@ -135,12 +137,28 @@ void hleEnterVblank(u64 userdata, int cyclesLate)
// Draw screen overlays before blitting. Saves and restores the Ge context.
/*
if (g_Config.bShowGPUStats)
gpuStats.numFrames++;
// This doesn't work very well yet. PPGe is probably not a great choice to do custom overlays
// as we're not really sure which framebuffer it will end up in at this point.
if (false && g_Config.bShowDebugStats)
{
char stats[512];
sprintf(stats, "Draw calls")
}*/
sprintf(stats,
"Frames: %i\n"
"Draw calls: %i\n"
"Textures loaded: %i\n",
gpuStats.numFrames,
gpuStats.numDrawCalls,
TextureCache_NumLoadedTextures());
/*
PPGeBegin();
PPGeDrawText(stats, 2, 2, 0, 0.3f, 0x90000000);
PPGeDrawText(stats, 0, 0, 0, 0.3f);
PPGeEnd();
*/
gpuStats.resetFrame();
}
// Yeah, this has to be the right moment to end the frame. Give the graphics backend opportunity
// to blit the framebuffer, in order to support half-framerate games that otherwise wouldn't have
@ -149,6 +167,7 @@ void hleEnterVblank(u64 userdata, int cyclesLate)
{
host->EndFrame();
host->BeginFrame();
gpu->BeginFrame();

View File

@ -40,6 +40,7 @@
#include "DisplayListInterpreter.h"
#include "Framebuffer.h"
#include "TransformPipeline.h"
#include "TextureCache.h"
#include "../../Core/HLE/sceKernelThread.h"
#include "../../Core/HLE/sceKernelInterrupt.h"
@ -92,6 +93,8 @@ void GLES_GPU::InitClear()
void GLES_GPU::BeginFrame()
{
TextureCache_Decimate();
if (g_Config.bDisplayFramebuffer && displayFramebufPtr_)
{
INFO_LOG(HLE, "Drawing the framebuffer");

View File

@ -35,6 +35,10 @@
#include "TextureCache.h"
// If a texture hasn't been seen for 200 frames, get rid of it.
#define TEXTURE_KILL_AGE 200
struct TexCacheEntry
{
u32 addr;
@ -77,6 +81,28 @@ void TextureCache_Clear(bool delete_them)
}
}
// Removes old textures.
void TextureCache_Decimate()
{
// TODO: Need a better way to keep looping
restart:
for (TexCache::iterator iter = cache.begin(); iter != cache.end(); ++iter)
{
if (iter->second.frameCounter + TEXTURE_KILL_AGE < gpuStats.numFrames)
{
glDeleteTextures(1, &iter->second.texture);
cache.erase(iter);
goto restart;
}
}
}
int TextureCache_NumLoadedTextures()
{
return cache.size();
}
u32 GetClutAddr(u32 clutEntrySize)
{
return ((gstate.clutaddr & 0xFFFFFF) | ((gstate.clutaddrupper << 8) & 0x0F000000)) + ((gstate.clutformat >> 16) & 0x1f) * clutEntrySize;
@ -395,9 +421,9 @@ u16 convert5551(u16 c) {
struct DXT1Block
{
u8 lines[4];
u16 color1;
u16 color2;
u8 lines[4];
};
inline u32 makecol(int r, int g, int b, int a)
@ -525,24 +551,20 @@ void PSPSetTexture()
if (match) {
//got one!
entry.frameCounter = gpuStats.numFrames;
glBindTexture(GL_TEXTURE_2D, entry.texture);
UpdateSamplingParams();
DEBUG_LOG(G3D,"Texture at %08x Found in Cache, applying", texaddr);
DEBUG_LOG(G3D, "Texture at %08x Found in Cache, applying", texaddr);
return; //Done!
} else {
NOTICE_LOG(G3D,"Texture different or overwritten, reloading at %08x", texaddr);
//Damnit, got overwritten.
//if (dim != entry.dim)
//{
// glDeleteTextures(1, &entry.texture);
//}
INFO_LOG(G3D, "Texture different or overwritten, reloading at %08x", texaddr);
glDeleteTextures(1, &entry.texture);
cache.erase(iter);
}
}
else
{
NOTICE_LOG(G3D,"No texture in cache, decoding...");
INFO_LOG(G3D,"No texture in cache, decoding...");
}
//we have to decode it
@ -552,6 +574,7 @@ void PSPSetTexture()
entry.addr = texaddr;
entry.hash = *(u32*)texptr;
entry.format = format;
entry.frameCounter = gpuStats.numFrames;
if(format >= GE_TFMT_CLUT4 && format <= GE_TFMT_CLUT32)
{
@ -565,8 +588,6 @@ void PSPSetTexture()
}
glGenTextures(1, &entry.texture);
NOTICE_LOG(G3D, "Creating texture %i", entry.texture);
glBindTexture(GL_TEXTURE_2D, entry.texture);
u32 bufw = gstate.texbufwidth[0] & 0x3ff;
@ -576,6 +597,8 @@ void PSPSetTexture()
u32 w = 1 << (gstate.texsize[0] & 0xf);
u32 h = 1 << ((gstate.texsize[0]>>8) & 0xf);
NOTICE_LOG(G3D, "Creating texture %i from %08x: %i x %i (stride: %i). fmt: %i", entry.texture, entry.addr, w, h, bufw, entry.format);
gstate_c.curTextureWidth=w;
gstate_c.curTextureHeight=h;
GLenum dstFmt = 0;
@ -587,6 +610,8 @@ void PSPSetTexture()
// TODO: Look into using BGRA for 32-bit textures when the GL_EXT_texture_format_BGRA8888 extension is available, as it's faster than RGBA on some chips.
// TODO: Actually decode the mipmaps.
switch (format)
{
case GE_TFMT_CLUT4:
@ -744,6 +769,7 @@ void PSPSetTexture()
i++;
}
}
finalBuf = tmpTexBuf32;
}
break;

View File

@ -20,4 +20,6 @@
void PSPSetTexture();
void TextureCache_Clear(bool delete_them);
void TextureCache_Clear(bool delete_them);
void TextureCache_Decimate(); // Run this once per frame to get rid of old textures.
int TextureCache_NumLoadedTextures();

View File

@ -224,6 +224,8 @@ void TransformAndDrawPrim(void *verts, void *inds, int prim, int vertexCount, Li
useTexCoord = true;
}
}
gpuStats.numDrawCalls++;
gpuStats.numVertsTransformed += vertexCount;
// Then, transform and draw in one big swoop (urgh!)
// need to move this to the shader.
@ -479,11 +481,13 @@ void TransformAndDrawPrim(void *verts, void *inds, int prim, int vertexCount, Li
{
// We have to turn the rectangle into two triangles, so 6 points. Sigh.
// top left
// TODO: there's supposed to be extra magic here to rotate the UV coordinates depending on if upside down etc.
// bottom right
*trans = transVtx;
trans++;
// bottom right
// top left
*trans = transVtx;
trans->x = saved.x;
trans->uv[0] = saved.uv[0];

View File

@ -268,8 +268,19 @@ struct GPUStateCache
// TODO: Implement support for these.
struct GPUStatistics
{
void reset() {
memset(this, 0, sizeof(this));
}
void resetFrame() {
numDrawCalls = 0;
numVertsTransformed = 0;
numTextureSwitches = 0;
numShaderSwitches = 0;
}
// Per frame statistics
int numDrawCalls;
int numVertsTransformed;
int numTextureSwitches;
int numShaderSwitches;