Quick answer: Surfaces live in volatile GPU memory and can vanish on alt-tab, resolution change, or device loss. Check surface_exists every frame and recreate + repopulate when gone.
A game caches a lighting buffer in a surface. After the player alt-tabs, the screen goes black — the surface was freed by the OS and never recreated.
Always Guard Surface Use
// Draw event
if (!surface_exists(light_surf)) {
light_surf = surface_create(surf_w, surf_h);
rebuild_lighting(); // repopulate contents
}
surface_set_target(light_surf);
// ... draw lights ...
surface_reset_target();
Never assume a surface persists across frames. Check, recreate, repopulate.
Separate Creation from Population
Keep the “rebuild contents” logic in its own function. Both initial setup and post-loss recovery call it. Don’t duplicate the drawing code.
Application Surface
The built-in application_surface can also be lost. GameMaker recreates it automatically, but if you draw to it manually, guard with surface_exists(application_surface) too.
Resolution Changes
Switching fullscreen/windowed or changing resolution often invalidates surfaces. If you size surfaces to the window, recreate them on the Window Resize event as well.
Verifying
Alt-tab away and back. The lighting surface rebuilds; no black screen. Toggle fullscreen; surfaces resize and repopulate.
“Surfaces are volatile GPU memory. Treat every frame as if the surface might be gone.”
Wrap surface access in a helper: get_surface(ref, w, h) that checks, creates, and returns — one safe path instead of scattered surface_exists checks.