SDL: fixed LRU cache code

From fe405eb27b9a21ff9f16543fa41a39eb0d72fd90 Mon Sep 17 00:00:00 2001
From: stdgregwar <[EMAIL REDACTED]>
Date: Mon, 28 Dec 2020 14:00:53 +0100
Subject: [PATCH] fixed LRU cache code

---
 src/render/psp/SDL_render_psp.c | 71 ++++++++++++++++++++++++++-------
 1 file changed, 56 insertions(+), 15 deletions(-)

diff --git a/src/render/psp/SDL_render_psp.c b/src/render/psp/SDL_render_psp.c
index 28e01c0e1d7..c93942837da 100644
--- a/src/render/psp/SDL_render_psp.c
+++ b/src/render/psp/SDL_render_psp.c
@@ -56,6 +56,12 @@ static unsigned int __attribute__((aligned(16))) DisplayList[262144];
 #define COL4444(r,g,b,a)    ((r>>4) | ((g>>4)<<4) | ((b>>4)<<8) | ((a>>4)<<12))
 #define COL8888(r,g,b,a)    ((r) | ((g)<<8) | ((b)<<16) | ((a)<<24))
 
+//#define LOGGING
+#ifdef LOGGING
+#define LOG(...) printf(__VA_ARGS__)
+#else
+#define LOG(...)
+#endif
 /**
  * Holds psp specific texture data
  *
@@ -220,37 +226,31 @@ LRUTargetRelink(PSP_TextureData* psp_texture) {
     }
 }
 
-static void
+/*static void
 LRUTargetFixTail(PSP_RenderData* data, PSP_TextureData* psp_texture) {
     if(data->least_recent_target == psp_texture) {
         data->least_recent_target = psp_texture->prevhotw;
     } else if(!data->least_recent_target) {
         data->least_recent_target = psp_texture;
     }
-}
+}*/
 
 static void
 LRUTargetPushFront(PSP_RenderData* data, PSP_TextureData* psp_texture) {
+    LOG("Pushing %p (%dKB) front.\n", (void*)psp_texture, psp_texture->size / 1024);
     psp_texture->nexthotw = data->most_recent_target;
     if(data->most_recent_target) {
         data->most_recent_target->prevhotw = psp_texture;
     }
-    LRUTargetFixTail(data, psp_texture);
-}
-
-static void
-LRUTargetBringFront(PSP_RenderData* data, PSP_TextureData* psp_texture) {
-    if(data->most_recent_target == psp_texture) {
-        return; //nothing to do
+    data->most_recent_target = psp_texture;
+    if(!data->least_recent_target) {
+        data->least_recent_target = psp_texture;
     }
-    LRUTargetRelink(psp_texture);
-    psp_texture->prevhotw = NULL;
-    psp_texture->nexthotw = NULL;
-    LRUTargetPushFront(data, psp_texture);
 }
 
 static void
 LRUTargetRemove(PSP_RenderData* data, PSP_TextureData* psp_texture) {
+    LOG("Removing %p (%dKB).\n", (void*)psp_texture, psp_texture->size/1024);
     LRUTargetRelink(psp_texture);
     if(data->most_recent_target == psp_texture) {
         data->most_recent_target = psp_texture->nexthotw;
@@ -262,6 +262,37 @@ LRUTargetRemove(PSP_RenderData* data, PSP_TextureData* psp_texture) {
     psp_texture->nexthotw = NULL;
 }
 
+static void
+LRUTargetBringFront(PSP_RenderData* data, PSP_TextureData* psp_texture) {
+    LOG("Bringing %p (%dKB) front.\n", (void*)psp_texture, psp_texture->size/1024);
+    if(data->most_recent_target == psp_texture) {
+        return; //nothing to do
+    }
+    //LRUTargetRelink(psp_texture);
+    LRUTargetRemove(data, psp_texture);
+    LRUTargetPushFront(data, psp_texture);
+}
+
+#ifdef LOGGING
+static void
+LRUWalk(PSP_RenderData* data) {
+    PSP_TextureData* tex = data->most_recent_target;
+    LOG("================\nLRU STATE:\n");
+    size_t size = 0;
+    while(tex) {
+        LOG("Tex %p (%dKB)\n", (void*)tex, tex->size/1024);
+        size+= tex->size;
+        if(tex->nexthotw && tex->nexthotw->prevhotw != tex) {
+            LOG("Spurious link!\n");
+        }
+        tex = tex->nexthotw;
+    }
+    LOG("Total Size : %dKB\n", size/1024);
+    size_t latest_size = data->least_recent_target ? data->least_recent_target->size : 0;
+    LOG("Least recent %p (%dKB)\n================\n", data->least_recent_target, latest_size / 1024);
+}
+#endif
+
 static void
 TextureStorageFree(void* storage) {
     if(InVram(storage)) {
@@ -436,13 +467,20 @@ TexturePromoteToVram(PSP_RenderData* data, PSP_TextureData* psp_texture, SDL_boo
 }
 
 static int
-TextureSpillLRU(PSP_RenderData* data) {
+TextureSpillLRU(PSP_RenderData* data, size_t wanted) {
     PSP_TextureData* lru = data->least_recent_target;
     if(lru) {
         if(TextureSpillToSram(data, lru) < 0) {
             return -1;
         }
+        LOG("Spilled %p (%dKB) to ram", (void*)lru, lru->size/1024);
         LRUTargetRemove(data, lru);
+        #ifdef LOGGING
+        LRUWalk(data);
+        #endif
+    } else {
+        SDL_SetError("Could not spill more VRAM to system memory. VRAM : %dKB,(%dKB), wanted %dKB", vmemavail()/1024, vlargestblock()/1024, wanted/1024);
+        return -1; //Asked to spill but there nothing to spill
     }
     return 0;
 }
@@ -451,7 +489,7 @@ static int
 TextureSpillTargetsForSpace(PSP_RenderData* data, size_t size)
 {
     while(vlargestblock() < size) {
-        if(TextureSpillLRU(data) < 0) {
+        if(TextureSpillLRU(data, size) < 0) {
             return -1;
         }
     }
@@ -470,6 +508,9 @@ TextureBindAsTarget(PSP_RenderData* data, PSP_TextureData* psp_texture) {
         }
     }
     LRUTargetBringFront(data, psp_texture);
+    #ifdef LOGGING
+    LRUWalk(data);
+    #endif
     sceGuDrawBufferList(psp_texture->format, vrelptr(psp_texture->data), psp_texture->textureWidth);
     return 0;
 }