• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Any way to get better FPS by downscaling a full HD game?

Z

zendorf

Guest
Is there any way of downscaling a game for better performance on a weaker system?

My game is a native Full HD/ 60fps game that runs fine even on a HD4000. However, I am trying to get it to run better on even lower end laptops that have non-hd screens (1366x768 and 1280x720).

I started this game way back in GMS 1.3 then briefly in 1.4 and am now working on it in GMS2.

When the application surface feature first arrived in GMS1.3 I was able to use surface_resize(application_surface, 1280, 720) to downscale the game to a lower resolution to get a much better real FPS. For some reason when GMS1.4 arrived, the same code would not run better with downscaling. Even if I did something crazy like 600x400 in windowed mode, it would still have the same real FPS as if it was full HD.

To clarify, I am not having any issues with the look of the game or aspect ratio, etc,(all is working fine for that) I am purely trying to get a better real FPS at low resolution. This did work in 1.3, but not since and I have tried all sorts of tricks to get it to, but to no avail. Surely since less pixels are being draw (Full HD vs 720p) I should get better performance?

Any help would be much appreciated!
 

GMWolf

aka fel666
If you are using views, you may need to scale the view surfaces down as well.

Aside from that, I don't see why there would be a difference between 1.3 and 1.4
 
Z

zendorf

Guest
Thanks for the reply. By "view surfaces" do you mean the view itself? I have tried scaling the view_set_wport and hport, but it made no difference in fps. Keep in mind I am now on GMS2, and views have been changed...
 

RangerX

Member
How do you proceed to downscale the game? This is probably where the problem lies. If you draw your stuff in the surface in full hd (1920x1080) then you resize that surface there's no perfomance gain because everything had to be drawn full hd anyways. Its the same memory and process time + the time to resize the surface.
 
Z

zendorf

Guest
@RangerX thanks for your reply. So when I use surface_resize(application_surface, 1280, 720) to resize, it is resizing the FullHD screen after it has drawn all elements? I had thought that it had resized the surface then drawn everything at the smaller scale.

I have tried scaling the window size, view size etc, but with no effect on real FPS. Is there any way of going about this correctly in GMS2 to get a better FPS, or will I always get the same performance as the original Full HD?
 
Z

zendorf

Guest
@Fel666 thanks for the link. I just tried adding this in , but was getting almost instant crashes and very odd freezes. Since GMS2 is still in beta, I am not sure if this even works properly, and more to the point not sure if this will even give better FPS at lower res. Unless there is a safe/easy way to do this I think I will leave it or the time being...it is not imperative.

I have been trying a current build on my game on a very low end Celeron Acer machine, and am actually quite surprised how much better it is running using GMS2/DX11. There is quite a massive boost in FPS and I am getting a fairly solid 60fps (as compared to GMS1.4) on most levels, so I am fairly happy. I also have a "quality" setting that I have built into many parts of my code that scales down the number of particles and BG objects, etc which helps greatly.

My base level machine is a HD4000, and it runs fine on that so I guess I have to draw the line somewhere and call it a day. Otherwise someone with an Atom chip and 1280x720 will get pissed that they can't get a solid framerate :)
 

RangerX

Member
You need to understand the draw pipeline.

1- GMS draws the tiles and backgrounds on the application surface
2- Object are drawing what they have to draw (including themselves) on the application surface
3- Application surface is drawn to screen.

So basically if starting number 1 your app surf is 1920x1080 then everything is drawn on it high res. After that if you resize it between 2 and 3, you understand that all the drawing has been done already. The draw calls is what takes the juice my friend. You want better FPS on lower machines = you should draw less high res. Downscaling is almost always a bad idea. No matter how you spin this. Games are generally upscaling not downscaling.
 

GMWolf

aka fel666
You need to understand the draw pipeline.

1- GMS draws the tiles and backgrounds on the application surface
2- Object are drawing what they have to draw (including themselves) on the application surface
3- Application surface is drawn to screen.

So basically if starting number 1 your app surf is 1920x1080 then everything is drawn on it high res. After that if you resize it between 2 and 3, you understand that all the drawing has been done already. The draw calls is what takes the juice my friend. You want better FPS on lower machines = you should draw less high res. Downscaling is almost always a bad idea. No matter how you spin this. Games are generally upscaling not downscaling.
The idea is to scale the surface down before drawing to it.
You can do that on game start.
That way you cam render at 1/2 res and scale up...
 

RangerX

Member
Yes, but then its useless since the game won't look high res anyways.
He totallt can have different view size, app surf sizes depending the machine/monitor the game is played in. I am just not sure its what he wants. And this is tuff to manage depending the type of game.
 

GMWolf

aka fel666
Yes, but then its useless since the game won't look high res anyways.
He totallt can have different view size, app surf sizes depending the machine/monitor the game is played in. I am just not sure its what he wants. And this is tuff to manage depending the type of game.
Plenty of games allow you to select the render resolution for performance reasons... It makes a lot of sense.
 

obscene

Member
I've never understood how cropping off half your game to lower the resolution is an acceptable solution. I've just come to face the hard fact that my game is hard-coded at 1920x1080 and there's nothing that can be done about it. Resizing the application surface has zero effect, and I don't know how you could possibly support multiple resolutions in a 2D game other than having multiple sizes for every sprite in your game and adding code to choose between them and then modify every single draw call to multiply scale by a global variable. And after all that I'm still pretty certain that wouldn't result in better FPS.

So I've just chose to make up for it by making everything else as customizable as possible like lighting, particles, shader fidelity, vsync, anti-aliasing, framerate (easily the simplest most beneficial option), etc.
 
Z

zendorf

Guest
You need to understand the draw pipeline.

1- GMS draws the tiles and backgrounds on the application surface
2- Object are drawing what they have to draw (including themselves) on the application surface
3- Application surface is drawn to screen.

So basically if starting number 1 your app surf is 1920x1080 then everything is drawn on it high res. After that if you resize it between 2 and 3, you understand that all the drawing has been done already. The draw calls is what takes the juice my friend. You want better FPS on lower machines = you should draw less high res. Downscaling is almost always a bad idea. No matter how you spin this. Games are generally upscaling not downscaling.
Cheers, I am now clear as to how that works. For some reason I thought that resizing the application surface was the first step and the engine would dynamically scale all objects. Now that I know how it really works, of course there is no reason to try to downscale.

I will leave in my scaling option in the menu, so that the player can have the option of having a floating window at various sizes. As I stated earlier, I am happy with the performance increase since going to GMS2, so that gives me a lot more wiggle room with performance on a weak laptop. Eventually I will also compile with the YYC, but am leaving that till GMS2 is out of beta. I have a ton of trig functions in my code, so this should give me a nice boost in performance.
 
Z

zendorf

Guest
Plenty of games allow you to select the render resolution for performance reasons... It makes a lot of sense.
I would imagine if you were doing a 2d game in a 3d engine like Unity or Godot, then this would work as everything is just textured quads. Picking a lower res would definitely give better performance. Even though GMS is still really using textured quads for each sprite, I guess you lose this this potential performance gain because of its drawing pipeline?
 
Z

zendorf

Guest
I've never understood how cropping off half your game to lower the resolution is an acceptable solution. I've just come to face the hard fact that my game is hard-coded at 1920x1080 and there's nothing that can be done about it. Resizing the application surface has zero effect, and I don't know how you could possibly support multiple resolutions in a 2D game other than having multiple sizes for every sprite in your game and adding code to choose between them and then modify every single draw call to multiply scale by a global variable. And after all that I'm still pretty certain that wouldn't result in better FPS.

So I've just chose to make up for it by making everything else as customizable as possible like lighting, particles, shader fidelity, vsync, anti-aliasing, framerate (easily the simplest most beneficial option), etc.
Agreed...this is the same conclusion I have come to. I also have similar settings to yours for dialling down the quality. Interestingly enough it is rare to see this in a 2d game, although it is standard for a 3d one.

There is not much info around on this topic for gamemaker(hence my post) as most people are doing low res/pixel art and want to know how to scale everything up...
 

RangerX

Member
Plenty of games allow you to select the render resolution for performance reasons... It makes a lot of sense.
A large majority of games where you select the resolution also change the resolution of your monitor! The problem with GMS is that we can't do that.
 

GMWolf

aka fel666
I would imagine if you were doing a 2d game in a 3d engine like Unity or Godot, then this would work as everything is just textured quads
So is gamemaker. Just textured polygons.

A large majority of games where you select the resolution also change the resolution of your monitor!
? Do they?
What you really want to do though is change the render resolution and then scale up. Less lixles to write to will mean you use fewer of the graphics card's pixelf fill rate. (And possibly texel rate too).

This will improve performance, and it is an acceptable solution.
Too many people believe 720p is an abomination and should never be used on a 1080p monitor. But the truth is that 720p looks very good (not as good as 1080p), and in the middle of the action, it really won't matter. (Remember that YouTube 720p is not the same as game 720p).
So for someone that can't quite run the game a full resolution, being able to run the game at a lower res is very nice.

Not to mention, not everyone has a 1080p monitor. A lot of laptops ship with lower resolutions.
Its much better to render to native resolution than to have to scale down.
 
M

MishMash

Guest
Just wanted to chip in a few thoughts:

- Generally, the primary reason a game should have resolution change support is so that the game can look "correct" at multiple different playable resolutions, rather than for a straight-up performance scaling feature.

Generally speaking, unless we are talking crazy-high resolutions, the actual render resolution is unlikely to be the main source of slow-down in your game. What tends to happen however is that as the resolution gets larger, the already-existing issues with the efficiency of your draw process get compounded.

To go over a few common issues that nuke the performance of games (Far more than resolution itself):

  • Fillrate saturation:
    When you render any object to the screen, it has to draw pixels. If you draw multiple objects on top of each other, you can end up in a situation where you render the same pixel multiple times. Even if you are rendering at quite a small resolution, if every pixel is getting rendered 4 times, but you are only actually seeing the colour of the final pixel to be drawn, you are wasting a lot of potential processing power.
    Solutions:
    - Re-structure your draw order so that the top-most object is rendered first. (The reason for this will become clear in a moment).
    - For non-transparent sprites (we cannot apply this optimisation to transparent objects as they rely on compounding sequences of colours, and thus are the biggest offenders of fillrate saturation), we can enable draw_set_enable_alpha_test(true); This discards processing on fully transparent pixels below a certain threshold.
    - We can also set draw_enable_alphablend(false); to further turn off alpha blending.

  • Drawing batch breaks:
    This one is a little more complicated. When it comes to rendering, one of the most common bottlenecks is the exchange of data between the GPU and the CPU. This is because when data is being sent, neither the CPU or GPU are doing anything. They are both sat there waiting for this slow data exchange to happen. This data exchange happens whenever you want to draw anything to the screen, or change any property (such as colour) associated with what is being drawing. These functions for example: draw_set_colour, draw_set_alpha, draw_sprite; (A big one is when the actively used texture changes).

    In order to optimise this, GameMaker uses a process called batching, where it groups together draw calls of sprites that are stored on the same texture page, because it only needs to submit information to the GPU in one go. However, every time you change the rendering colour, or use a different sprite in the middle, or switch render targets (anything like this), the batch breaks, and gets split up. The more fragmented the batch is, the more idle time you get where neither the CPU nor GPU is doing a whole lot. (Note: In this case, the Intel HD 4000 still acts as a discrete GPU, even though it is integrated).

    An easy way to see if this is happening is to use the profiler to evaluate how long is spent after each function. More importantly, using a GPU benchmarking tool can reveal GPU usage. If your GPU usage is low, but your game is still running poorly, this is indicative of an inefficient rendering pipeline.

    Solutions:
    - Optimise your texture pages manually to group together objects that are often rendered at the same time.
    - Try and remove unnecessary colour swaps / shader uniform changes, and do them once at the start of each group of rendering, rather than individually for each object.
    - Create one central object that is responsible for coordinating all rendering (rather than having it distributed amongst all objects.) What this can mean is that rather than having each object run its own draw event in sequence, have one object invoke the draw event of each object at a specific time. This will give you more control over the order in which things render, allowing you to optimise more heavily.

  • Random render settings:
    Make sure you haven't got anything like vsync enabled. Test your game with fast vertex mode enabled (in global game settings).

I hope these suggestions help you look at your rendering pipeline with a little more depth, just beyond what the resolution itself is doing. What you will often find is that higher resolutions cause you to reach a "crash" faster. (This is where the GPU suddenly can't keep up with what you are telling it to do, and performance will just drop really quickly).

This is not to say downscaling wont help, its just that downscaling and other things like frame-skipping often just hide the true cause of major slow-down. The annoying thing about downscaling is that once you've done it, there isn't much more you can do. If you then decide to add more fancy effects, well, then you've lost your flexibility for further optimisation. So yeah, still downscale if it helps, but try some other solutions as well.

The final thing to say is that you mentioned downscaling not working well in GMS 1.4+, this may be because you are still rendering the same number of objects. Offscreen rendering can also be expensive if you are submitting things from drawing that cant be seen. A better approach to downscaling would be to instead disable the application surface, and use your own back-end surface that you have more control over. The application surface can get goofy when it comes to things like the GUI layer.
 
Z

zendorf

Guest
@MishMash thanks for that writeup, it is very useful! Btw, Just noticed that GMS2 doesn't have a fast vertex mode in Windows>Graphics options like 1.4 ...
 
M

MishMash

Guest
@MishMash thanks for that writeup, it is very useful! Btw, Just noticed that GMS2 doesn't have a fast vertex mode in Windows>Graphics options like 1.4 ...
Fast vertex mode isn't all that significant. In GMS2.0, there is no need to worry about this because the default windows pipeline uses DirectX 11 vs DirectX 9, so that change alone should be faster than the difference you would get from fast vertex mode.
 
Z

zendorf

Guest
@MishMash thanks for that writeup, it is very useful! Btw, Just noticed that GMS2 doesn't have a fast vertex mode in Windows>Graphics options like 1.4 ...
Fast vertex mode isn't all that significant. In GMS2.0, there is no need to worry about this because the default windows pipeline uses DirectX 11 vs DirectX 9, so that change alone should be faster than the difference you would get from fast vertex mode.
Ok, thanks, that is good to know. GMS2 does indeed provide a massive speedup compared to GMS1.4, which I would imagine is mainly due to DX11.
 
Top