@@ -296,7 +296,7 @@ static uint32_t countFreeChunks(GsRenderer* gs) {
296296
297297// Find the atlas with the oldest lastUsed time (LRU victim).
298298// Returns the atlasId, or -1 if no loaded atlases.
299- static int16_t findLRUVictim (GsRenderer * gs ) {
299+ static int16_t findLRUVictim (GsRenderer * gs , bool * wasUsedOnThisFrame ) {
300300 uint64_t oldest = UINT64_MAX ;
301301 int16_t victimAtlas = -1 ;
302302 forEach (VRAMChunk , chunk , gs -> chunks , gs -> chunkCount ) {
@@ -305,6 +305,8 @@ static int16_t findLRUVictim(GsRenderer* gs) {
305305 victimAtlas = chunk -> atlasId ;
306306 }
307307 }
308+ if (victimAtlas != -1 )
309+ * wasUsedOnThisFrame = oldest == gs -> frameCounter ;
308310 return victimAtlas ;
309311}
310312
@@ -351,10 +353,20 @@ static int32_t allocateChunks(GsRenderer* gs, int chunksNeeded) {
351353
352354 // Attempt 2: evict LRU victims one at a time until space is found
353355 repeat (gs -> chunkCount , attempts ) {
354- int16_t victim = findLRUVictim (gs );
356+ bool wasUsedOnThisFrame = false;
357+
358+ int16_t victim = findLRUVictim (gs , & wasUsedOnThisFrame );
355359 if (0 > victim )
356360 break ;
357361
362+ // We only need to flush if the victim was used on this frame
363+ // If it wasn't, then we can evict with no care in the world
364+ if (wasUsedOnThisFrame ) {
365+ fprintf (stderr , "GsRenderer: Flushing draw queue before VRAM evicting because atlas was used on the current frame\n" );
366+ gs -> evictedAtlasUsedInCurrentFrame = true;
367+ gsKit_queue_exec (gs -> gsGlobal );
368+ }
369+
358370 evictAtlas (gs , victim );
359371
360372 idx = findConsecutiveFreeChunks (gs , chunksNeeded );
@@ -363,6 +375,11 @@ static int32_t allocateChunks(GsRenderer* gs, int chunksNeeded) {
363375 return idx ;
364376 }
365377
378+ // At this point we are lost, just flush and hope for the best
379+ gs -> evictedAtlasUsedInCurrentFrame = true;
380+ fprintf (stderr , "GsRenderer: Flushing draw queue before VRAM defrag\n" );
381+ gsKit_queue_exec (gs -> gsGlobal );
382+
366383 // Attempt 3: defrag - evict ALL and let them reload on demand
367384 // Handles fragmentation where enough free chunks exist but aren't consecutive
368385 if (countFreeChunks (gs ) >= (uint32_t ) chunksNeeded ) {
@@ -901,6 +918,7 @@ static void gsBeginFrame(Renderer* renderer, MAYBE_UNUSED int32_t gameW, MAYBE_U
901918 GsRenderer * gs = (GsRenderer * ) renderer ;
902919 gs -> zCounter = 1 ;
903920 gs -> frameCounter ++ ;
921+ gs -> evictedAtlasUsedInCurrentFrame = false;
904922}
905923
906924static void gsEndFrame (MAYBE_UNUSED Renderer * renderer ) {
0 commit comments