diff --git a/Core/HLE/__sceAudio.cpp b/Core/HLE/__sceAudio.cpp index 89338fb447..c59567077f 100644 --- a/Core/HLE/__sceAudio.cpp +++ b/Core/HLE/__sceAudio.cpp @@ -209,12 +209,12 @@ void __AudioUpdate() outAudioQueue.push((s16)sampleL); outAudioQueue.push((s16)sampleR); } + } else { + // This happens quite a lot. There's still something slightly off + // about the amount of audio we produce. + DEBUG_LOG(HLE, "Audio outbuffer overrun! room = %i / %i", outAudioQueue.room(), (u32)outAudioQueue.capacity()); } section.unlock(); - } else { - // This happens quite a lot. There's still something slightly off - // about the amount of audio we produce. - DEBUG_LOG(HLE, "Audio outbuffer overrun! room = %i / %i", outAudioQueue.room(), (u32)outAudioQueue.capacity()); } } diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index d047027cdc..8b14908cb9 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -208,7 +208,7 @@ void hleEnterVblank(u64 userdata, int cyclesLate) { // Here we will be drawing to the non buffered front surface. if (g_Config.bShowDebugStats && gpuStats.numDrawCalls) { gpu->UpdateStats(); - char stats[512]; + char stats[2048]; sprintf(stats, "Frames: %i\n" "DL processing time: %0.2f ms\n" @@ -217,6 +217,7 @@ void hleEnterVblank(u64 userdata, int cyclesLate) { "Draw calls: %i\n" "Draw flushes: %i\n" "Vertices Transformed: %i\n" + "FBOs active: %i\n" "Textures active: %i\n" "Textures decoded: %i\n" "Texture invalidations: %i\n" @@ -231,6 +232,7 @@ void hleEnterVblank(u64 userdata, int cyclesLate) { gpuStats.numDrawCalls, gpuStats.numFlushes, gpuStats.numVertsTransformed, + gpuStats.numFBOs, gpuStats.numTextures, gpuStats.numTexturesDecoded, gpuStats.numTextureInvalidations, diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index 2d7aee60e2..cb862d3f34 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -37,6 +37,11 @@ extern u32 curTextureWidth; extern u32 curTextureHeight; +// Aggressively delete unused FBO:s to save gpu memory. +enum { + FBO_OLD_AGE = 4 +}; + const int flushOnChangedBeforeCommandList[] = { GE_CMD_VERTEXTYPE, GE_CMD_BLENDMODE, @@ -200,6 +205,7 @@ void GLES_GPU::DumpNextFrame() { void GLES_GPU::BeginFrame() { TextureCache_StartFrame(); + DecimateFBOs(); if (dumpNextFrame_) { NOTICE_LOG(G3D, "DUMPING THIS FRAME"); @@ -277,6 +283,17 @@ void GLES_GPU::CopyDisplayToOutput() { BeginDebugDraw(); } +void GLES_GPU::DecimateFBOs() { + for (auto iter = vfbs_.begin(); iter != vfbs_.end();) { + if ((*iter)->last_frame_used + FBO_OLD_AGE < gpuStats.numFrames) { + fbo_destroy((*iter)->fbo); + vfbs_.erase(iter++); + } + else + ++iter; + } +} + GLES_GPU::VirtualFramebuffer *GLES_GPU::GetDisplayFBO() { for (auto iter = vfbs_.begin(); iter != vfbs_.end(); ++iter) { if (((*iter)->fb_address & 0x3FFFFFF) == (displayFramebufPtr_ & 0x3FFFFFF)) { @@ -345,6 +362,7 @@ void GLES_GPU::SetRenderFrameBuffer() { vfb->height = drawing_height; vfb->format = fmt; vfb->fbo = fbo_create(vfb->width * renderWidthFactor_, vfb->height * renderHeightFactor_, 1, true); + vfb->last_frame_used = gpuStats.numFrames; vfbs_.push_back(vfb); fbo_bind_as_render_target(vfb->fbo); glstate.viewport.set(0, 0, renderWidth_, renderHeight_); @@ -362,6 +380,7 @@ void GLES_GPU::SetRenderFrameBuffer() { fbo_bind_as_render_target(vfb->fbo); glstate.viewport.set(0, 0, renderWidth_, renderHeight_); currentRenderVfb_ = vfb; + vfb->last_frame_used = gpuStats.numFrames; } } @@ -1064,6 +1083,7 @@ void GLES_GPU::UpdateStats() { gpuStats.numFragmentShaders = shaderManager_->NumFragmentShaders(); gpuStats.numShaders = shaderManager_->NumPrograms(); gpuStats.numTextures = TextureCache_NumLoadedTextures(); + gpuStats.numFBOs = vfbs_.size(); } void GLES_GPU::DoBlockTransfer() { diff --git a/GPU/GLES/DisplayListInterpreter.h b/GPU/GLES/DisplayListInterpreter.h index 88b1ab0f6c..690ca4f5d2 100644 --- a/GPU/GLES/DisplayListInterpreter.h +++ b/GPU/GLES/DisplayListInterpreter.h @@ -63,6 +63,9 @@ private: void BeginDebugDraw(); void EndDebugDraw(); + // Deletes old FBOs. + void DecimateFBOs(); + FramebufferManager framebufferManager; TransformDrawEngine transformDraw_; ShaderManager *shaderManager_; @@ -86,6 +89,8 @@ private: }; struct VirtualFramebuffer { + int last_frame_used; + u32 fb_address; u32 z_address; int fb_stride; diff --git a/GPU/GLES/TextureCache.cpp b/GPU/GLES/TextureCache.cpp index 14aec11244..3f592cd98c 100644 --- a/GPU/GLES/TextureCache.cpp +++ b/GPU/GLES/TextureCache.cpp @@ -61,11 +61,12 @@ u16 *clutBuf16; void TextureCache_Init() { // TODO: Switch to aligned allocations for alignment. AllocateMemoryPages would do the trick. - tmpTexBuf32 = new u32[1024 * 512]; - tmpTexBuf16 = new u16[1024 * 512]; - tmpTexBufRearrange = new u32[1024 * 512]; - clutBuf32 = new u32[4096]; - clutBuf16 = new u16[4096]; + // This is 5MB of temporary storage. Might be possible to shrink it. + tmpTexBuf32 = new u32[1024 * 512]; // 2MB + tmpTexBuf16 = new u16[1024 * 512]; // 1MB + tmpTexBufRearrange = new u32[1024 * 512]; // 2MB + clutBuf32 = new u32[4096]; // 4K + clutBuf16 = new u16[4096]; // 4K } void TextureCache_Shutdown() { diff --git a/GPU/GPUState.h b/GPU/GPUState.h index dfbd97dec8..2580d73518 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -283,6 +283,7 @@ struct GPUStatistics int numVertexShaders; int numFragmentShaders; int numShaders; + int numFBOs; }; void InitGfxState();