Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MacBook Pro quickly maxes out its memory when running a project on Compatibility rendering method with ANGLE #85619

Closed
sandord opened this issue Dec 1, 2023 · 16 comments · Fixed by #85785

Comments

@sandord
Copy link

sandord commented Dec 1, 2023

Godot version

4.2.stable (.NET version)

System information

macOS Ventura 13.6.1, MacBook 2017 Intel Core i5, Iris Plus 650, 16 GB ram

Issue description

My friend was testing my Godot project (which has the Compatibility rendering method configured) and he said that his MacBook quickly ran out of memory. The game was allocating 15 GB of RAM after a minute or two. More interestingly, the same happened with the 2D platformer demo project from https://github.com/godotengine/godot-demo-projects, when running in Compatibility mode. My Windows machine doesn't suffer from this at all.

Fortunately, we figured out that switching to Forward+ mode fixed the issue. The downside is that I have now lost a potential audience of devices that need Compatibility rendering.

Here's what he saw in the profiler:

WhatsApp Image 2023-12-01 at 17 00 58_40cb5e91

By the way, when my friend closes the editor, he gets the following which might be related (I have no idea but who knows):

image

Steps to reproduce

Run the 2D platformer demo project from https://github.com/godotengine/godot-demo-projects and set it to the Compatibility rendering method (or possibly any other game that can run in this mode) on a MacBook (maybe only one that matches the provided system specs or maybe any Mac, I don't know).

Minimal reproduction project

2D/platformer demo from https://github.com/godotengine/godot-demo-projects in Compatibility rendering mode

@alakoring
Copy link

alakoring commented Dec 1, 2023

I’m seeing something similar (also with 4.2.stable). Running my game and watching its memory usage in Activity Monitor (MacBook Pro M1, macOS 12.7), memory keeps climbing. It starts around 768 Mb. The Godot editor remains around 1.61 GB but the game is now up to 12 GB and has the spinning pizza.

I switched from Compatibility renderer to Mobile and memory for my game remains under 730 MB. (The editor takes a little more than under Compatibility but is stable in both configurations.)

@bfarnsey
Copy link

bfarnsey commented Dec 1, 2023

Thank you for posting this - switched from Compatibility to Forward+ and now my game is working again. Before it was freezing after 75-85 seconds, and only if I had a UI control node visible, and it was doing my head in. Could not reproduce on Windows or Linux, only Mac.

@sonic2kk
Copy link

sonic2kk commented Dec 1, 2023

I believe Compatibility uses OpenGL, and macOS has poor support for OpenGL. Mobile and Forward+ use Vulkan (by way of MoltenVK a Metal-to-Vulkan translationl layer iirc), which would explain the discrepancy. Windows and Linux generally have better support for OpenGL (and also Vulkan fwiw).

@Calinou
Copy link
Member

Calinou commented Dec 1, 2023

Can you reproduce this in 4.1.3? If not, please check 4.2 dev/beta/RC builds for this issue as well to determine when the regression started: https://downloads.tuxfamily.org/godotengine/4.2/

I believe Compatibility uses OpenGL, and macOS has poor support for OpenGL. Mobile and Forward+ use Vulkan (by way of MoltenVK a Metal-to-Vulkan translationl layer iirc), which would explain the discrepancy. Windows and Linux generally have better support for OpenGL (and also Vulkan fwiw).

ANGLE is used by default in Godot 4.2 on macOS, so that its own Metal backend is used instead of Apple's own OpenGL-over-Metal layer. It's also used on Windows on old GPUs by default to circumvent issues with their buggy OpenGL drivers.

You can control whether ANGLE is used in the Project Settings, or using the --rendering-driver command line argument.

@alakoring
Copy link

I switched from Compatibility renderer to Mobile and memory for my game remains under 730 MB.

May have spoken too soon — I left my game running for several hours and it hit around 14 GB of memory and was no longer responding to events (beachball cursor). I’ll have to try to repeat this but it was at least an hour (with the Mobile renderer). So far I haven’t had luck attaching the Leaks instrument.

@alakoring
Copy link

Going back to 4.1.3, Compatibility renderer might have the slow leak (pretty sure it’s not my code) but not the quick one.

@HolySkyMin
Copy link
Contributor

Disabling ANGLE (--rendering-driver opengl3 or changing it in the project setting) worked for me. With ANGLE, even drawing a single button leads to 50MB of memory leak every single time Activity Monitor refreshes.

@akien-mga akien-mga added this to the 4.3 milestone Dec 4, 2023
@akien-mga akien-mga changed the title My friend's MacBook Pro quickly maxes out its memory when running a project on Compatibility rendering method MacBook Pro quickly maxes out its memory when running a project on Compatibility rendering method with ANGLE Dec 4, 2023
@bruvzg

This comment was marked as outdated.

@HolySkyMin
Copy link
Contributor

I want to test it but ANGLE does not apply when I build Godot myself.
스크린샷 2023-12-05 오후 8 45 38

@bruvzg
Copy link
Member

bruvzg commented Dec 5, 2023

I want to test it but ANGLE does not apply when I build Godot myself.

To build with ANGLE you need to download static libs from https://github.com/godotengine/godot-angle-static and build with angle_libs=path/to/angle/libs flag.

@HolySkyMin
Copy link
Contributor

Still reproducible in current master.

Something weird is, when the window is hidden by other application, it will stop increasing its memory usage; if it is visible, it starts consuming memory again.

@bruvzg
Copy link
Member

bruvzg commented Dec 5, 2023

I can't reproduce it with current master on M1 Mac, 2D/platformer demo with ANGLE OpenGL rendering driver stay at constant 155 ± 3 MB (at least for a half hour).

Actually, I was running it with the wrong binary without ANGLE, so it was a native GL result. I can confirm a leak with ANGLE:

IOGPUResourceCreate	
-[IOGPUMetalResource initWithDevice:remoteStorageResource:options:args:argsSize:]	
-[IOGPUMetalBuffer initWithDevice:pointer:length:alignment:options:sysMemSize:gpuAddress:args:argsSize:deallocator:]	
-[AGXBuffer(Internal) initWithDevice:length:alignment:options:isSuballocDisabled:resourceInArgs:pinnedGPULocation:]	
-[AGXBuffer initWithDevice:length:alignment:options:isSuballocDisabled:pinnedGPULocation:]	
rx::mtl::ContextDevice::newBufferWithLength(unsigned long, unsigned long) const	
rx::mtl::Buffer::reset(rx::ContextMtl*, MTLStorageMode, unsigned long, unsigned char const*)	
rx::mtl::Buffer::Buffer(rx::ContextMtl*, MTLStorageMode, unsigned long, unsigned char const*)	
rx::mtl::Buffer::MakeBufferWithStorageMode(rx::ContextMtl*, MTLStorageMode, unsigned long, unsigned char const*, std::__1::shared_ptr<rx::mtl::Buffer>*)	
rx::mtl::BufferPool::allocateNewBuffer(rx::ContextMtl*)	
rx::mtl::BufferPool::allocate(rx::ContextMtl*, unsigned long, unsigned char**, std::__1::shared_ptr<rx::mtl::Buffer>*, unsigned long*, bool*)	
rx::ProvokingVertexHelper::preconditionIndexBuffer(rx::ContextMtl*, std::__1::shared_ptr<rx::mtl::Buffer>, unsigned long, unsigned long, bool, gl::PrimitiveMode, gl::DrawElementsType, unsigned long&, unsigned long&, gl::PrimitiveMode&, std::__1::shared_ptr<rx::mtl::Buffer>&)	
rx::ContextMtl::drawElementsImpl(gl::Context const*, gl::PrimitiveMode, int, gl::DrawElementsType, void const*, int, int, unsigned int)	
rx::ContextMtl::drawElementsInstanced(gl::Context const*, gl::PrimitiveMode, int, gl::DrawElementsType, void const*, int)	
gl::Context::drawElementsInstanced(gl::PrimitiveMode, int, gl::DrawElementsType, void const*, int)	
GL_DrawElementsInstanced	
RasterizerCanvasGLES3::_render_batch(RendererCanvasRender::Light*, unsigned int)	
RasterizerCanvasGLES3::_render_items(RID, int, Transform2D const&, RendererCanvasRender::Light*, bool&, bool)	
RasterizerCanvasGLES3::canvas_render_items(RID, RendererCanvasRender::Item*, Color const&, RendererCanvasRender::Light*, RendererCanvasRender::Light*, Transform2D const&, RenderingServer::CanvasItemTextureFilter, RenderingServer::CanvasItemTextureRepeat, bool, bool&)	
RendererCanvasCull::_render_canvas_item_tree(RID, RendererCanvasCull::Canvas::ChildItem*, int, RendererCanvasCull::Item*, Transform2D const&, Rect2 const&, Color const&, RendererCanvasRender::Light*, RendererCanvasRender::Light*, RenderingServer::CanvasItemTextureFilter, RenderingServer::CanvasItemTextureRepeat, bool, unsigned int)	
RendererCanvasCull::render_canvas(RID, RendererCanvasCull::Canvas*, Transform2D const&, RendererCanvasRender::Light*, RendererCanvasRender::Light*, Rect2 const&, RenderingServer::CanvasItemTextureFilter, RenderingServer::CanvasItemTextureRepeat, bool, bool, unsigned int)	
RendererViewport::_draw_viewport(RendererViewport::Viewport*)	
RendererViewport::draw_viewports(bool)	
RenderingServerDefault::_draw(bool, double)	
Main::iteration()	
OS_MacOS::run()	

@bfarnsey
Copy link

bfarnsey commented Dec 5, 2023

Still reproducible in current master.

Something weird is, when the window is hidden by other application, it will stop increasing its memory usage; if it is visible, it starts consuming memory again.

This is reproduceable. If I keep the window focused, it’ll last about 75 seconds before freezing. When I have another window focused, it’ll chug on merrily behind.

@bruvzg

This comment was marked as outdated.

@sect2k
Copy link

sect2k commented Dec 5, 2023

Still reproducible in current master.

Something weird is, when the window is hidden by other application, it will stop increasing its memory usage; if it is visible, it starts consuming memory again.

This is probably a side effect of App Nap feature in MacOS and not caused by godot itself.

@bruvzg
Copy link
Member

bruvzg commented Dec 5, 2023

I think I see what's wrong, https://github.com/godotengine/godot-angle-static is built with disabled ARC support (there's no way to build it otherwise) and Godot is using ARC. This seems to be causing some resources to leak. With the external libraries, it seems to work.

No, it's still no leaking, so no idea.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment