Author Topic: Battlescape performance  (Read 18737 times)

Online Yankes

  • Global Moderator
  • Commander
  • *****
  • Posts: 3348
    • View Profile
Battlescape performance
« on: August 14, 2011, 04:14:31 am »
bug a was probably caused by the caching of the tiles. I removed caching (the shading effect is now done with palette tricks), and as a result this bug is also fixed :)

.
btw in last build moving animation slowed down, FPS counter drop from 300 to 150 when i moved my solder. after move ends it goes back to 300
« Last Edit: August 14, 2011, 09:28:48 pm by michal »

Offline Daiky

  • Battlescape Programmer
  • Administrator
  • Commander
  • *****
  • Posts: 904
    • View Profile
Battlescape performance
« Reply #1 on: August 14, 2011, 02:26:29 pm »
yes, I'm kinda desperate if changing the palettes is really taking so much time. The problem is, you can not access the internal palette map directly to just set the colors. (Which was certainly possible in the old days)

If I look into the SDL code, the call to set the SDL_SetPalette , it seems to do so many weird things like allocating a new memory,  running through all colors and map it to something. So it's a pretty busy function.
Knowing that a battlescape screen easely can have around 300 objects to draw...

You will notice that a mission in full daylight will go faster, because I already added an optimization that if the palette does not need to be changed, it doesn't call the palette change function.

The default rate at which the whole screen is redrawn is 10fps (which is the speed of the animation of for example the little arrow above the soldier's head, or animation of fire, smoke and other stuff). All the other frames in between are drawn from the buffer.
The walking animation is at 25fps - unfortunatly it also redraws the whole screen (on top of the 10fps of the animation drawing) - which is 35 times it draws 300 objects from scratch. So yeah, that's more than 1000 calls per second the setPalette function - if it really is allocating and deallocating memory at 1.000 times per second, it is not surprising it has time to only get 150 frames shown on the screen within that second.


I got another trick up my sleeve... which also is used in almost every 2D game (almost certainly in the original x-com as well).... It is called "dirty rects" - it's as nasty to implement as it sounds.
The idea is to only redraw the parts of the screen that have changed on the new frame and get all the rest from the last frame...

Volutar

  • Guest
Battlescape performance
« Reply #2 on: August 14, 2011, 02:54:21 pm »
"Dirty rects" technique actually used in original XCom series (1-3). For faster re-rendering it uses number of tile sequences to redraw when moved in different directions (unit movement, projectile fly, explosions). Though it has small artefacs. Anyway it's a good thing.

Offline Daiky

  • Battlescape Programmer
  • Administrator
  • Commander
  • *****
  • Posts: 904
    • View Profile
Battlescape performance
« Reply #3 on: August 14, 2011, 06:35:11 pm »
Anyway it's a good thing.
In theory at least :)
But when moving to higher resolution screens, it becomes even more important, so I hope to get good results after I manage to implement it.

Online Yankes

  • Global Moderator
  • Commander
  • *****
  • Posts: 3348
    • View Profile
Battlescape performance
« Reply #4 on: August 14, 2011, 08:39:01 pm »
i dont think that will help much. when you move solder in dark, every tiles change its light amount. this will cause more than half screen force to update, and probably number of calls of setPalette dont change.

but it would be possible to group object that have same palette? and draw them at once? it will have problems with position, but using some kind of Z-buffer will probably solve most of problems.

Offline Daiky

  • Battlescape Programmer
  • Administrator
  • Commander
  • *****
  • Posts: 904
    • View Profile
Re: Battlescape performance
« Reply #5 on: August 14, 2011, 09:36:17 pm »
Yankes, the light changes only at the very end of the walking cycle, so only one frame out of the 8 or 16 (diagonal step) frames - so I still think a performance gain is possible.

The idea to group drawings that have the same palette is good, but I'm not sure how to implement the Z-buffer you mention.

Offline Daiky

  • Battlescape Programmer
  • Administrator
  • Commander
  • *****
  • Posts: 904
    • View Profile
Re: Battlescape performance
« Reply #6 on: August 14, 2011, 11:03:24 pm »
So, I was thinking, each tile corresponds to a rectangle of 32x40, when a tile goes invalid this is the rectangle that needs to be re-blitted. But the tiles that need to be redrawn are actually not just the invalid tile, but also the 3 tiles in front of it?
You also see that with a soldier movement or projectile, there is always a begin-tile and end-tile - so maximum two rectangles to update. (if a soldier just turns around or kneels, it's only one)
And these two rectangles can be merged into one.



edit: actually it's not just the 3 tiles in front of it... It's more like everything in front of it :)
« Last Edit: August 14, 2011, 11:14:57 pm by Daiky »

Offline panther

  • Sergeant
  • **
  • Posts: 42
    • View Profile
Re: Battlescape performance
« Reply #7 on: August 15, 2011, 02:02:13 am »
yes, I'm kinda desperate if changing the palettes is really taking so much time. The problem is, you can not access the internal palette map directly to just set the colors. (Which was certainly possible in the old days)
...

This must be due to the fact that "in the old days", a change of palette colors would natively affect all pixels of that color in the next redraw because you changed the graphic cards lookup table. Modern graphics don't work this way but work on a bitmap where each pixel has his own color value 16-32bit. Without looking at the SDL code, I suppose on a palette change, it must find all pixels of that color and change it's color value accordingly. The palette mode really is an "emulation" costing performance.

In short, palette changes are far from efficient operations anymore. Better to redraw only dirty regions as you suggested.
« Last Edit: August 15, 2011, 02:03:50 am by panther »

Offline Daiky

  • Battlescape Programmer
  • Administrator
  • Commander
  • *****
  • Posts: 904
    • View Profile
Re: Battlescape performance
« Reply #8 on: August 15, 2011, 02:20:49 pm »
Been experimenting with dirty rectangles, so far it just gives me loads of artifacts :)

Online Yankes

  • Global Moderator
  • Commander
  • *****
  • Posts: 3348
    • View Profile
Re: Battlescape performance
« Reply #9 on: August 15, 2011, 04:31:17 pm »
Been experimenting with dirty rectangles, so far it just gives me loads of artifacts :)
alien artifacts ? :)

i think a bit about this `Z-buffer`. probably best solution is add new surface that will store this as white color byte.
to draw something you will need call that pseudo code:
Code: [Select]
int currZ;
int buffZ[n][k];
color buffDraw[n][k];
color tile[tile_h][tile_w];
int x,y;
for(i=0; i<tile_h; ++i)
    for(j=0; j<tile_w; ++j)
    {
        if(tile[i][j] != transparent && buffZ[x+i][y+j]<currZ)
        {
            buffDraw[x+i][y+j] = tile[i][j];
            buffZ[x+i][y+j] = currZ;
        }
    }
i think this will be more slow than current solution, because of this `if` and need of drawing every pixel separate.

Offline Daiky

  • Battlescape Programmer
  • Administrator
  • Commander
  • *****
  • Posts: 904
    • View Profile
Re: Battlescape performance
« Reply #10 on: August 15, 2011, 04:49:44 pm »
After 2 days of experimenting with different methods. I decided to go back to the previous method of caching tiles... at the cost of memory usage. But at least it worked and is very simple :p
What this means is, that the terrain is cached in memory. Terrain = floor tile+wall tiles+objects+items. So if terrain does not changes, it saves 4 blits & 5 palette changes per tile on the screen.

On my system (high-end) I got :
previous build : 890fps static screen - 650fps during walking
current build: 950fps static screen - 920fps during walking

It will be more interesting to see the results on normal systems :)

Volutar

  • Guest
Re: Battlescape performance
« Reply #11 on: August 15, 2011, 05:19:03 pm »
Original xcom has number of redraw patterns (tile sequences) for 8 directions of movement for single unit, for 2x2 unit, for standing unit. (17 pattarns + 1 large pattern for everything else). predefined patterns. different levels aren't in count, it just render lower levels with same pattern but  shifted north-east.

Online Yankes

  • Global Moderator
  • Commander
  • *****
  • Posts: 3348
    • View Profile
Re: Battlescape performance
« Reply #12 on: August 15, 2011, 05:36:54 pm »
i find bug in new cache tiles, when titles are change off screan, they stay in previous state. best way to reproduce it is chare your solder to alien and kill him away from rest of your squad.
next when you want see place where he died, you can see not updated titles, you need move cursor over them to update them
[ps]
now i have idle: 420 move: 350
older  idle: 340 move: 130

« Last Edit: August 15, 2011, 06:05:02 pm by Yankes »

Online Yankes

  • Global Moderator
  • Commander
  • *****
  • Posts: 3348
    • View Profile
Re: Battlescape performance
« Reply #13 on: August 23, 2011, 06:38:55 pm »
Daiky i have question, how bliting works when you have two different palettes? when i set all palette colors in surface to white and i blit it to surface that have only black color?

Offline SupSuper

  • Lazy Developer
  • Administrator
  • Commander
  • *****
  • Posts: 2162
    • View Profile
Re: Battlescape performance
« Reply #14 on: August 23, 2011, 07:16:44 pm »
Daiky i have question, how bliting works when you have two different palettes? when i set all palette colors in surface to white and i blit it to surface that have only black color?
SDL tries to find the closest matches for each color from the source palette in the destination palette (in your example you'd just get a black surface since that's the only color available in the destination palette).