GameMaker "Unbalanced surface stack" Error? [Solved]

PlayerOne

Member
Just updated GMS2 with the new installer. Ran project to ensure everything worked and I got this error:

Code:
"ERROR!!! :: Unbalanced surface stack. you are trying to pop a surface that has not been set."
Cleaned the project and still got the same result. I didn't change anything before updating and it worked fine without problems.
 
S

Satori

Guest
Same thing happened to me. Apparently there have been some changes to the way surfaces are being used. This article goes into more detail:
https://www.yoyogames.com/blog/493/using-surfaces

In my case, I was using surface_reset_target() more than once after using surface_set_target(). Removing the extra surface_reset_target() solved the problem. Make sure you only have one surface_reset_target() for each surface_set_target(). (Thanks again to JeffJ for pointing out that article to me.)
 
P

ph101

Guest
Also if you resize a surface in code block when a surface has been set you will get this. If that's the case you will need to resize it elsewhere.
 

PlayerOne

Member
Same thing happened to me. Apparently there have been some changes to the way surfaces are being used. This article goes into more detail:
https://www.yoyogames.com/blog/493/using-surfaces

In my case, I was using surface_reset_target() more than once after using surface_set_target(). Removing the extra surface_reset_target() solved the problem. Make sure you only have one surface_reset_target() for each surface_set_target(). (Thanks again to JeffJ for pointing out that article to me.)
I only have one surface_set_target and surface_reset_target.

This is the only object that uses surfaces.

Code:
var lt = _light
var view_x = camera_get_view_x(view_camera[0]);
var view_y = camera_get_view_y(view_camera[0]);
var viewport_w = camera_get_view_width(view_camera[0])
var viewport_h =camera_get_view_height(view_camera[0])


if (surface_exists(lt))
{


surface_set_target(lt)
draw_clear(c_black)
   


   if instance_exists(par_light)
   {
       
       
       with(par_light)
       {
       
       gpu_set_blendmode(bm_subtract);
       draw_sprite_ext(sprite_index,0,x-view_x,y-view_y,image_xscale,image_yscale,image_angle,c_green,1)
       gpu_set_blendmode(bm_normal);       
       
       
       
       }
   

   
   }

       surface_reset_target();
       draw_surface_ext(lt,view_x,view_y,1,1,0,c_white,darkness);
}
else
{
_light = surface_create(viewport_w,viewport_h);   
}
Oddly if press "ignore" when the error pops up on compile it will run without issue.
 
S

Satori

Guest
Well I don't see any obvious problems with the code, but why are there 2 different variables (lt and _light) for the surface? If I'm following correctly, it looks like if the surface doesn't exist, it doesn't get created until the end of the code, in which case it won't be used until the code runs again in the next step. Is there a reason for doing it that way? When I work with surfaces, I put something like this at the beginning of the code block:
Code:
if !surface_exists(surf)
    surf = surface_create(surfwidth, surfheight);
That way, if the surface doesn't already exist, it gets created in the same step it's being used and you don't have to wrap everything in an if/else statement. I don't know if that will solve your problem, but it's worth a try.
 
S

Satori

Guest
Also, do you have a surface_free() statement anywhere?

From the manual:
When you are working with surfaces, you should always use this function whenever you are finished using them. Surfaces take up space in memory and so need to be removed, normally at the end of a room, but it can be done at any time depending on the use you put them to. Failure to do so can cause memory leaks which will eventually slow down and crash your game.
 

PlayerOne

Member
Well I don't see any obvious problems with the code, but why are there 2 different variables (lt and _light) for the surface? If I'm following correctly, it looks like if the surface doesn't exist, it doesn't get created until the end of the code, in which case it won't be used until the code runs again in the next step. Is there a reason for doing it that way? When I work with surfaces, I put something like this at the beginning of the code block:
Code:
if !surface_exists(surf)
    surf = surface_create(surfwidth, surfheight);
That way, if the surface doesn't already exist, it gets created in the same step it's being used and you don't have to wrap everything in an if/else statement. I don't know if that will solve your problem, but it's worth a try.
_light is the primary varible to hold the surface and var lt orignally held a global that eventually got replaced with _light. Also, yes I have surface_free() in the Clean Up event.

I made the changes as you requested above and got the same error message anyway. At this point it's probably nothing since if I press ignore it runs as normal.
 
S

Satori

Guest
Well I'm stumped. Maybe someone else will have some suggestions.

When exactly does the error pop up? When you first start the game? After performing a specific action in the game? At random intervals?
 

PlayerOne

Member
Well I'm stumped. Maybe someone else will have some suggestions.

When exactly does the error pop up? When you first start the game? After performing a specific action in the game? At random intervals?
Just on compile and at no other point. Don't know what to make of it really. Could be a bug with GMS2? At this point I'm throwing darts at the wall.
 
P

ph101

Guest
Curious what happens if you move the surface exists/create to the top as satori suggests and then remove the use of the var lt and use _light directly... (if genuinely there is no other surface target setting or surface use in any way at all pehaps it is a bug you have found where the counting of surface setting/resetting is thrown off if the surface is in a local var as you have done?)
 

PlayerOne

Member
Curious what happens if you move the surface exists/create to the top as satori suggests and then remove the use of the var lt and use _light directly... (if genuinely there is no other surface target setting or surface use in any way at all pehaps it is a bug you have found where the counting of surface setting/resetting is thrown off if the surface is in a local var as you have done?)
Got rid of var lt with the exception of a few that set the surface size and position and placed the creation of the surface at the top, nothing changed. However this error pops up on compile and no where else from what I found.

I'm temped to comment out all of the surface code then re-compile again to see if that does anything.
 

Tsa05

Member
What if you put surface_free at the end of your code block there, instead of in your cleanup event? I feel as though it shouldn't make a difference, but...what if?
 

PlayerOne

Member
What if you put surface_free at the end of your code block there, instead of in your cleanup event? I feel as though it shouldn't make a difference, but...what if?
Wouldn't that delete the surface? Causing an endless loop of creation and destroy?
 
P

ph101

Guest
with the exception of a few that set the surface size and position
I would be interested to see if it worked if you removed use of the local var entirely (why do you have it all - it seems totally unnecessary anyway even if it *should* work). Also, unless I am being blind I dont see that resizing code posted above? Are you altering the surface in other areas? You should post all the code, as I mentioned in my first post above, from my low level understanding, surface resize can affect this.

edit. yes of course to help further your understanding, if you comment out all the surface code and still get the error, you must be using surfaces elsewhere in error. You could also search whole project for relevant surface functions with ctrl + shift + f
 

PlayerOne

Member
I would be interested to see if it worked if you removed use of the local var entirely (why do you have it all - it seems totally unnecessary anyway even if it *should* work). Also, unless I am being blind I dont see that resizing code posted above? Are you altering the surface in other areas? You should post all the code, as I mentioned in my first post above, from my low level understanding, surface resize can affect this.

edit. yes of course to help further your understanding, if you comment out all the surface code and still get the error, you must be using surfaces elsewhere in error. You could also search whole project for relevant surface functions with ctrl + shift + f
I use the remaing var as a short hand for the camera width, height, x, and y. This shouldn't be an issue. Unless you count resizing as having different camera width and height in the different room properties. Not modifying directly in gml or anything.

After more testing I commented out all surface_* functions in the clean up and draw events. Cleaned the the cache and compiled once more. Same result.
 
P

ph101

Guest
I dont understand as earlier you said you are using a local var to "set the surface size" as you say, but now you say as a short hand for the camera width? So perhaps I am misunderstanding. Do you resize the surface anywhere beacuse I didnt see the code for that.

Anyway, seems I can't help you further! Personally in your situation, I would

-Actually search the project using ctrl + shift + f for "surface" and check you didnt forget anything..?
-comment out all surface functions it returns
-post all the code here (included where you resize the surface if you do?), maybe someone else can help
-check if you are doing any thing with application surface targets (just a randomn thought that one)

If you still get the error then.. well I dont know what to say. How big is your project - you'll need to submit a bug. In most cases this error is caused by a mismatch in set or resetting target, or resizing it when set, seems you have discovered something else.
 
S

Satori

Guest
Just on compile and at no other point. Don't know what to make of it really. Could be a bug with GMS2? At this point I'm throwing darts at the wall.
You only get the error during compiling? So what would happen if you click the Build menu, click Create Executable, then run the executable from outside of the IDE? Do you get the error if you do that? If not, then you probably don't have anything to worry about because your players shouldn't ever see the message (in theory at least).
 

PlayerOne

Member
You only get the error during compiling? So what would happen if you click the Build menu, click Create Executable, then run the executable from outside of the IDE? Do you get the error if you do that? If not, then you probably don't have anything to worry about because your players shouldn't ever see the message (in theory at least).
You only get the error during compiling? So what would happen if you click the Build menu, click Create Executable, then run the executable from outside of the IDE? Do you get the error if you do that? If not, then you probably don't have anything to worry about because your players shouldn't ever see the message (in theory at least).
What if you put surface_free at the end of your code block there, instead of in your cleanup event? I feel as though it shouldn't make a difference, but...what if?
I screwed up. I followed PixelatedPope's tutorial once more on resolution and I messed up the process somehwere down the line. The error doesn't appear after fixing it.

Sorry for wasting your time on this everyone. Still no error appeared on screen before upgrading GMS2 so why this happened now and not then I don't know.
 
P

ph101

Guest
Still no error appeared on screen before upgrading GMS2 so why this happened now and not then I don't know.
Because they changed the way surfaces are used meaning you can't have an unbalanced surface target/reset in 2.2.1, its noted in the release notes and the first reply you got :p
 

bsabiston

Member
I'm getting this after updating. Sure would be useful if they would tell you WHERE it was being called incorrectly. I've looked at all my calls and they all seem to be matched, set with reset...

EDIT: well shut my mouth -- it does tell you, if you run in the debugger!
 
Top