GM:S Memory Management 101: Tricks and Clarity (sprite_add)

kupo15

Member
EDIT: Through the responses I learned there are other ways to create texture pages and do what I'm looking for so my main ask at the bottom has been resolved. Now just need to find one that integrates well with GM. This post now serves as a great resource of info regarding memory and other info found in the comments.

Hey everyone, I know I've posted quite a bit about this topic before and have gotten some answers regarding it. I wanted to post again with some new inquiries of my thoughts on this topic because this is probably the most important thing to creating big games.

Especially since 1.4 is being phased out of support next year I think understanding this topic is very important for those big projects like mine that are still in 1.4 and are hesitant to move over to Studio 2 bc of its size. I have a big question to YOYO games at the very end of this!

Sorry for the post being so large, I think its also a great comprehensive guide to memory in GM for those that don't know how it works.

Here is my understanding of it and I'm interested in feedback to my thoughts, if I'm wrong or not.

Overview
Memory

Big games require a lot of assets which take up memory and if you load everything at startup, you will run out of memory and your game won't work. This is why there are loading screens so that you swap in and out of memory the assets you need at one time.

Great! That means I can put as much stuff into GM and swap out what I need, right? Not exactly!

VRAM vs RAM
There are two things that make up memory, Vram and Ram. VRAM is the amount of memory your Graphics Card is using and RAM is the amount of memory the program/engine is using. They both have their own limits of how much memory/assets they can hold at one time!

Ex. If your program can hold 2GB of memory at one time but your Graphics Card can only hold 1GB of memory, that means your game can only use 1GB of memory at one time for your card. Other users Graphics Cards may be able to hold 2GB of memory so for them, they can run games that use up to 2GB of memory at one time.

So all I need to do is have a Graphics Card that holds 8GB and I can use more memory at one time, right!? No you can't for two reasons:
-Not everyone has cards that amazing so you are limiting your audience of your game to those people
-If your game engine can't hold 8GB of memory, then you can't fully use the 8GB your card can handle

GM:S Memory Limit
The memory limit for GM:S is about 1.7GB so you can't have more than this in your game at one time otherwise it will crash. This is a hard limit because GM:S is a 32bit program. If it were 64bit that number would be higher.

Not only can you not use more than 1.7GB at one time in the game, you can't have more than 1.7GB in your entire game engine period! This means that any resource you add directly into the resource tree will be eating up memory from the 1.7GB of game engine RAM. And no, you can't uncheck "load textures at start" to get around this. That only prevents your VRAM from being loaded up on startup

Man, I need more than 1.7GB for my game...I'm doomed because GM is only a 32bit program!
Good news is no you aren't! There are actually TWO loading mechanics GM has for memory management!

Here is a diagram showing the flow of memory limits

upload_2017-10-8_16-7-2.png


One is VRAM loading which was mentioned previous. VRAM is what gets drawn to your screen because its faster than normal RAM. GM pulls the assets you need to display from the game engine ram into the VRAM and uses that to draw to the screen.

The second type is External Loading into the Game Engine via sprite_add, sound_add etc! Here is where you can overcome GM:S's 1.7GB storage limit. Now the size of your HD is the limit to how much resources you can have in your game. In consoles, this limit was found in the size of the game disc.

However! Even though you can have 100s of GB of resources in your game (obviously not recommended) you still can only design your game around GM's 1.7GB RAM limit. The hard drive is just a big bin to store all unused resources until you want to pull them into Game Maker's Engine RAM.

So I don't need GM to be 64bit to make big games?
No not really. All you need to do is make sure no section of your game needs more than 1.7GB of memory at one time then you can make it as big as you want! (or as big as as much HD space you want to require) The 32bit program is only a limitation for you if you require more than 1.7GB to be used at one time which if you manage your resources well most likely won't really be problematic.

But wait, I thought we aren't supposed to use sprite_add anymore because they are bad and obsolete?
That is somewhat true, they are obsolete and are far inferior to putting your sprites directly into the IDE because you lose out on GM's amazing texture packing tool which is designed to use as little system memory as possible with sprites. Sprite_add also creates one texture page for each sprite (and subimage?) you add. So instead of having a small number of texture pages GM can pull things from, it will have to swap between the 100s of pages created using the sprite_add function.

Tips and Tricks
But that doesn't mean external loading is inherently bad and can still be used!

Audio

As far as I know, audio external loading doesn't suffer like sprite external loading does. If you put ALL your sound files directly into the IDE, all of those files will take away from the 1.7GB system limit. But chances are you don't need every sound file ready at all times so lots of sound files are unnecessarily using up valuable ram. Using sound_add functions helps to free up this space

Textures
If your resources are very high quality and big, chances are texture pages optimization aren't really going to help you minimize page swaps anyway so GM's built in texture packing isn't really that useful for you in this regard. Minimizing these swaps is important to game performance but it really is much more important for mobile games.

While its important to minimize swaps, desktops can handle more swaps without a performance hit. Texture page optimization will be important for reducing load times however.

Smart Texture external Loading
Backgrounds are the easiest texture resources to externally load while missing out on the built in texture packing tool. Menu backgrounds for example fill the whole screen and don't need to be in system ram all the time. They are perfect for the sprite_add functions because its also not that important for them to be packed tightly with game sprites and its ok that they can have their own texture page.

Game sprites (character animations, gfx etc..) is the only really tricky issue and is something that GM doesn't help you with if you want to go external with them. You can replicate the benefits of GM's built in texture packing tool with the sprite_add function but it would be a real pain. To do this you would need to:
-Load all your sprites directly into the IDE
-Go to the GGS and "preview" your texture pages
-This creates all the texture pages the game uses and you can use those massive cluster images as your sprite_add files
-The trick then is to figure out how to use sprite_draw_part on that massive jumbled image to draw the sprites you need for your animations

This is what GM does behind the scenes when your sprites are directly in the IDE. This is the updated sprite_add function that GM desperately needs! A sprite_add function that behaves exactly how it does when sprites are put directly into the IDE.

With this function the only true limitation will be your HD space and the 1.7GB of use at one time and memory limit worries will be almost non-existent. I believe this improved external loading is planned for GMS2 at some point which is great!


MY PLEA TO YOYO GAMES
Will this be coming to the GMS1 before support for 1.4 is discontinued next year? If it will not, is it possible that you can at least improve the Texture Preview feature in the GGS? In addition to creating the texture pages for us to use, can it also create a text file that includes all the data we need to easily reference the subimages in these texture pages we need for draw_sprite_part? GM must already do this under the hood and having access to it would make creating our own true external loading system much easier


Thanks!
 
Last edited:

YellowAfterlife

ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ
Forum Staff
Moderator
-Load all your sprites directly into the IDE
-Go to the GGS and "preview" your texture pages
-This creates all the texture pages the game uses and you can use those massive cluster images as your sprite_add files
-The trick then is to figure out how to use sprite_draw_part on that massive jumbled image to draw the sprites you need for your animations
That's an oddly complicated way. There are countless tools to generate texture pages in pretty much any format imaginable - even some web-based ones.

This is what GM does behind the scenes when your sprites are directly in the IDE. This is the updated sprite_add function that GM desperately needs! A sprite_add function that behaves exactly how it does when sprites are put directly into the IDE.
It may not be apparent, but texture packing is not done at runtime because it can be a very time-costly process. On some of the projects I've worked on it would take the editor 15 minutes to package a single 4096x4096 texture page just because of thousands individual elements creating a vast number of combinations to evaluate to be able to pick best-fitting one.

That said, if you absolutely insist on generating texture pages at runtime, there's this asset.
 

kupo15

Member
That's an oddly complicated way. There are countless tools to generate texture pages in pretty much any format imaginable - even some web-based ones.


It may not be apparent, but texture packing is not done at runtime because it can be a very time-costly process. On some of the projects I've worked on it would take the editor 15 minutes to package a single 4096x4096 texture page just because of thousands individual elements creating a vast number of combinations to evaluate to be able to pick best-fitting one.

That said, if you absolutely insist on generating texture pages at runtime, there's this asset.
Yep, I know of that runtime asset.. I'm refraining or prefer to keep things as native as possible. Also I believe the performance of that asset doesn't match that of GM's.

BUT you actually make a really great point and a great idea with pointing out my initial thoughts were overly complicated. If my main idea was to use sprite_add to load in texture pages manually and use draw_sprite_part, then extremely tight texture pages aren't 100% necessary. So if I use a sprite sheet generator that neatly aligns subimages in a row that'll make referencing them would be much easier! Is that the idea you were thinking?

Also another question for you. Do you believe that using the sprite_add function as is for animations which creates texture pages for each subimage is necessarily bad or would perform worse? My characters are big enough that even with GM's current texture packing system I can't save any swaps anyway. Not only that but each character has their own texture group so a swap between characters is inevitable. Even if both players chose the same character the chances of referencing the exact subimage for both characters are small.

I ask because simply using sprite_add I think will be easier to set up with the origin parameters it needs instead of using draw_sprite_part. It won't be as memory efficient as the sprite sheet way but as long as it keeps things under the 1.7 GB limit that efficiency loss shouldn't matter
 

Mike

nobody important
GMC Elder
Will this be coming to the GMS1 before support for 1.4 is discontinued next year?
There are no new features coming to 1.x.

There will never be a "runtime" creation of texture pages, it's just too slow (outside of simple Pow2 atlas generation).

We do have longer term plans to allow "bundles" of some kind so you can load (say) level 1 data pack in. but this would all be IDE generated at compile time, just allowing simpler loading/freeing of assets at runtime. This has been a wish for a while, so no idea "when" something like this may ever appear.
 
P

ph101

Guest
I would love to see control of sprite_add texture page as suggested by OP. Reason is I want to create sprites on the fly from different bits of sprite components and put them together as apsire with one draw call. @Mike what is your suggestion for this? Perhaps it is just don't? Or to design the game so the extra swaps don't matter?
 

Mike

nobody important
GMC Elder
google up texture atlas, its a simple recursive POW2 allocation system, which for dynamic stuff is probably best. Then just keep everything on surfaces and render from there, backing them up into RAM if need be.
 

kupo15

Member
There are no new features coming to 1.x.

There will never be a "runtime" creation of texture pages, it's just too slow (outside of simple Pow2 atlas generation).
Runtime creation as in creating new texture pages on the fly in runtime? (sounds like a silly obvious question lol) GM creates its texture pages when you compile the game right? If that is the difference you are making then that is not what I was asking for at all. I think its fine how GM create's its texture pages that they are premade.

I was just saying that since GM allows us to preview the texture pages and it creates those pages for us to see in our computer folder, it would be nice for it to also generate a text file with pointers to where the subimages are for us to use. Like

[animation1]
[subimage0]
texpage = 2
xx = 300;
yy = 400;
ww = 32
hh = 32;

etc

I imagine that GM somehow stores all of these references so that it knows where to find a specific subimage on the jumbled looking pages.

Maybe its not as important anymore from the idea of using external sprite sheet creations which neatly and orderly places the subimages together. Would still be cool to have access to the pointers GM stores when you hit Preview if that is what GM does

We do have longer term plans to allow "bundles" of some kind so you can load (say) level 1 data pack in. but this would all be IDE generated at compile time, just allowing simpler loading/freeing of assets at runtime. This has been a wish for a while, so no idea "when" something like this may ever appear.
From the sounds of it, this seems like it would only be a VRAM thing to make it easier to load what you need into VRAM, right? That would be cool and handy for sure but not something to make external loading easier or more efficient which would a blessing to have
 

YellowAfterlife

ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ
Forum Staff
Moderator
I was just saying that since GM allows us to preview the texture pages and it creates those pages for us to see in our computer folder, it would be nice for it to also generate a text file with pointers to where the subimages are for us to use. Like

[animation1]
[subimage0]
texpage = 2
xx = 300;
yy = 400;
ww = 32
hh = 32;

etc

I imagine that GM somehow stores all of these references so that it knows where to find a specific subimage on the jumbled looking pages.
There's a pile of XML files describing positioning of elements in a neighboring directory, but, as I have said above, there is arguably any sort of benefit of doing it that way instead of using a general-purpose external tool.
 

CMAllen

Member
I think what most of us want is a way to load up an image or create a surface (power of 2 in size, of course), define that image or surface as a texture page, and use that texture page to define sprites and their sub-images. And realistically speaking, there's no reason those functionalities cannot be exposed at run-time. They just *aren't* at this time.

To illustrate, if I want to take a series of 2048x images, layer them together on a 2048x surface, and use that final surface as a texture page (for example, customizable player sprites here), to define a bunch of new sprites, and generate all the bounds and properties of their sub-images, that's all basic functions that can be created in GM already...but only through a bunch of custom-written functions that require mostly rebuilding the drawing pipeline (since all your sprite assets will have to be referenced via draw_sprite_part() to be drawn properly) to get around the lack of the above mentioned functionalities. All I'm asking is that the underlying data structures and interfaces be exposed so that we can do this stuff ourselves. At least in code, at run-time. The IDE is fine for what it does. It's the stuff it does for us but does NOT let us do ourselves that isn't so great.

I've already broken down in some other thread what that would take in terms of bare minimum functionalities. They are as follows:
  • texture_from_surface(surface_id) //returns the texture_index for texture page.
  • texture_from_image(image_filename) //returns the texture_index of the texture page.
  • sprite_define(height, width) //returns the id of a new, empty sprite. Note: other sprite properties can be changed via existing functions, use default values for initial creation.
  • sprite_add_texture(sprite_index, texture_index, left, top) appends a new sub_image to the sprite_index value given.
And that's it. Just four functions that exist simply as a means of exposing some currently black-boxed data that GM manages and keeps (mostly) to itself. This data already exists. It's already being used and populated by the IDE. Just let us interact with it as well via native functions instead of interpreted ones that subsequently requires we throw out the existing drawing pipeline to create our own (ie, reinvent the wheel). That's why platforms like GMS2 exist -- so developers can stop reinventing the wheel. I could go wild with more functionalities, but those four cover enough of the basics that the rest are just 'nice to have' additions (things like inserting a new sub-image into an existing sprite, for example -- nice to have, but not necessary).
 

Mike

nobody important
GMC Elder
You can already do this using draw_surface_part()

Load in any image, Allocate the W,H from a surface (however you want to do this, there are several ways). switch blending off, draw loaded image to X,Y of the selected surface (blending off forces an alpha copy) then re-enable blending.
Form then on, you can simple draw parts of the surface. You can also backup the surface (if required) to a buffer for replacing if the surface is lost.

Allocation of a POW2 width/height from a surface is a simple process, but needs management. Taking a 1024x1024 surface and then allocating a 256x256, from it would require subdividing the 1024 into 4 512s, then 4 256s (leaving 3x512 in tact). Once you allocate the 256, you'll be left with 3x256, and 3x512 from the surface. This is usually best done in a recursive function, but doesn't have to be.

You can get the texture of the surface using surface_get_texture(surface_id)

All the tools are there already if you need them.
 

CMAllen

Member
You can already do this using draw_surface_part()

Load in any image, Allocate the W,H from a surface (however you want to do this, there are several ways). switch blending off, draw loaded image to X,Y of the selected surface (blending off forces an alpha copy) then re-enable blending.
Form then on, you can simple draw parts of the surface. You can also backup the surface (if required) to a buffer for replacing if the surface is lost.

Allocation of a POW2 width/height from a surface is a simple process, but needs management. Taking a 1024x1024 surface and then allocating a 256x256, from it would require subdividing the 1024 into 4 512s, then 4 256s (leaving 3x512 in tact). Once you allocate the 256, you'll be left with 3x256, and 3x512 from the surface. This is usually best done in a recursive function, but doesn't have to be.

You can get the texture of the surface using surface_get_texture(surface_id)

All the tools are there already if you need them.
Yes, they're all there. But using them requires more or less throwing out the existing drawing pipeline and creating your own to handle all of the data that GM is no longer managing for you -- origin points, image_index, x scale & y scale, image_angle, image_speed & sprite_speed, image_number -- there's a sizable list of data that GM manages that you would have to write all the functions to handle yourself, ie reinvent the wheel. That's no small task, nor should you so lightly suggest it as a 'solution.' That's killing a mosquito with a cannon. I'm saying add support for those functions into GML natively. No more working around arbitrary limitations. No more 'reinventing the wheel.' Expose that data to the user so that they can modify and interact with it. It doesn't need to be all encompassing in power and flexibility. Just enough to meet the basic necessities (as suggested previously).
 

kupo15

Member
There's a pile of XML files describing positioning of elements in a neighboring directory, but, as I have said above, there is arguably any sort of benefit of doing it that way instead of using a general-purpose external tool.
General purpose external tool like the Marketplace asset or the Leshy Sprite Packing? I agree now that you brought it up that I think that Leshy tool will be much easier and handier than the idea I originally suggested. Thanks for sharing it!
 

Mike

nobody important
GMC Elder
Yes, they're all there. But using them requires more or less throwing out the existing drawing pipeline and creating your own to handle all of the data that GM is no longer managing for you -- origin points, image_index, x scale & y scale, image_angle, image_speed & sprite_speed, image_number -- there's a sizable list of data that GM manages that you would have to write all the functions to handle yourself, ie reinvent the wheel. That's no small task, nor should you so lightly suggest it as a 'solution.' That's killing a mosquito with a cannon. I'm saying add support for those functions into GML natively. No more working around arbitrary limitations. No more 'reinventing the wheel.' Expose that data to the user so that they can modify and interact with it. It doesn't need to be all encompassing in power and flexibility. Just enough to meet the basic necessities (as suggested previously).
We can't implement everything, and we can't implement everything at the drop of hat. How about 3D sprites? how about a brand new particle system that deals with Physics? How about GPU based tile maps so you can render huge numbers of layers? How about new advertisers? How about upgrading Spine? how about implementing 2D lighting? Normal mapping? A full on 3D engine? A 3D editor? A make MMORPG button? </joke>

This list is literally endless. While we do have plans for "bundles" (as I explained above), we don't for general loading of sprite onto T-Pages. If you want this (as some games certainly will), you have enough tools to write this in GML, or you could do this as a native plugin, but I suspect GML would be fine. Some thing have to be done by us - shaders was a good example of this, and others can be deferred to end users to implement themselves.

This would obviously make a great marketplace item, and would certainly be general enough that others could easily use it. I've written these before for other engines and while it's not a tiny task, it's also not a huge one either. This is not one we're looking to do any time in the future I'm afraid.
 

JackTurbo

Member
Hi @Mike,

I'm just curious, you say bundles are planned for GMS2 (which sound awesome btw), but I dont see it on the GMS2 roadmap. Am I correct then in assuming that this is a long way off being looked at then? (personally I can wait, like i said I was just curious why I couldnt see it on the roadmap).

Thanks
 

Mike

nobody important
GMC Elder
This one is hard to say - which is why it's not on the list. We might be able to do it via some other work we do, and if we can, we'll sneak it in. but if we can't.... then yes, could be some time off.
 
S

SarbjitGrewal

Guest
General purpose external tool like the Marketplace asset or the Leshy Sprite Packing? I agree now that you brought it up that I think that Leshy tool will be much easier and handier than the idea I originally suggested. Thanks for sharing it!
Your spoiler Gif is terrible.
 

JackTurbo

Member
Your spoiler Gif is terrible.
Firstly thats his signature so has no relevance to the issue at hand and secondly thats early programmer art. Despite it being early programmer art it clearly demonstrates there is a lot going on there and that programmatically its quite an advanced project.

This is his project and frankly its one of the best looking and most ambitious projects on these boards.
https://forum.yoyogames.com/index.php?threads/rising-spirit-fighting-game.347/

And finally who are you to tell people that their projects are terrible!? - seriously not only is it simply incorrect in this case, its also just rude.
 

kupo15

Member
Yep, I thought about that...was like man I really did want to change it and not look reactive...but screw it! haha Thanks! :D
The old "terrible" gif is still on the first post of the game's forum post Jack linked to among the other prototype gifs as well
 

JackTurbo

Member
Kupo, when you sort out how youre gonna approach this issue fancy doing a write up of it here? Id be curious to hear how you eventually tackle the issue.
 

kupo15

Member
Yep, I've known about that. I'm trying to do my best not to use dll and do everything naively and myself if possible first. I also heard that even though its fast its still isn't as fast as GMS's draw speed. Anyone have experience using it out of curiosity?

Also might as well ask a couple more memory questions. In the debug module, is the memory display there the system ram and not vram? This isn't mentioned anywhere in the guide. I'm assuming its total system ram the game compiles with or increases if you add external assets? Does this number need to stay below the 1.7GB limit?

upload_2017-10-11_9-54-1.png
 

JackTurbo

Member
Am I correct in thinking that the 1.7gb limit this is only a major issue in GMS1?

GMS2 is large address aware right? So can access up to 4gb?
 

kupo15

Member
Am I correct in thinking that the 1.7gb limit this is only a major issue in GMS1?

GMS2 is large address aware right? So can access up to 4gb?
Yes that's correct for the most part. I don't think I'll ever need to use more than 1.7GB of memory at one time ever so that number doesn't seem like any concern there. If I did that would be a good reason to switch to GMS2. However I have no idea how much memory every asset in the game will use up to know if I can safely just include them all in the IDE. The IDE won't crash if its above 1.7 but it would crash at compile time.

The last thing I will want is to run out of memory 75% through the game and have to redo the entire system to be external with a launch date approaching. GMS2 will help as you said to raise the memory above that limit, but if the entire game needs 10GB of memory for example, it would still be a good idea to not require that from the users and I would still need to solve this external issue.

Wish I could estimate an accurate number of how much the game would need. If I knew that number was around 3-4GB I could safely switch to GMS2 and just bundle all the assets in the IDE
 

kupo15

Member
So does anyone know what memory the debug module refers to? There is no documentation about it



Is this the total memory used at compile time that chips away at that 1.7GB limit? As in, even if nothing is loaded in VRAM and your game is a blank room, your total asset memory is represented by this and can't go above 1.7GB?

@Mike
 

Mike

nobody important
GMC Elder
This is the total RUNTIME memory used, as you create new surfaces, instances, grids etc they all take up space. This will be limited to "around" 1.7GB.
 
Top