Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: [Solved] Drawing tiles, weird cpu usage  (Read 1594 times)

0 Members and 1 Guest are viewing this topic.

zaih

  • Newbie
  • *
  • Posts: 3
    • View Profile
[Solved] Drawing tiles, weird cpu usage
« on: November 27, 2011, 03:51:37 pm »
Hello,

I am creating a simple tile-engine based on a tutorial and at the moment trying to draw layers of tiles. Engine has simple camera system which keeps track of which tiles must be drawn on the screen. The problem here is related to drawing layers. Here's an example of drawing bottom layer:

Code: [Select]
  for(int y = 0, tileY = tileBounds.Top; y < tileBounds.Height; y++, tileY++)
   {
      for(int x = 0, tileX = tileBounds.Left; x < tileBounds.Width; x++, tileX++)
      {
         //let's assume that bottom layer must be filled with tiles --> no null check
         tile = currentLevel->GetLayer(0).GetTile(tileX, tileY);

         tile->Draw((x* tileSize) - camOffset_x, (y*tileSize) - camOffset_y, *window);
      }
   }


Now if I want to draw another layer: Consider adding next line under tile->Draw:
Code: [Select]
        tile = currentLevel->GetLayer(1).GetTile(tileX, tileY);
         if(tile != 0)
           tile->Draw((x* tileSize) - camOffset_x, (y*tileSize) - camOffset_y, *window);


If I now move the camera to an area which is filled with tiles from both layers, cpu usge is around 70-80%. In case I use separate loops for both layers, cpu usage is below 20%.

Example (this is faster!):
Code: [Select]
  for(int y = 0, tileY = tileBounds.Top; y < tileBounds.Height; y++, tileY++)
   {
      for(int x = 0, tileX = tileBounds.Left; x < tileBounds.Width; x++, tileX++)
      {
         //let's assume that bottom layer must be filled with tiles --> no null check
         tile = currentLevel->GetLayer(0).GetTile(tileX, tileY);

         tile->Draw((x* tileSize) - camOffset_x, (y*tileSize) - camOffset_y, *window);
         
      }
   }
 
   //Draw layer 1
   
   for(int y = 0, tileY = tileBounds.Top; y < tileBounds.Height; y++, tileY++)
   {
      for(int x = 0, tileX = tileBounds.Left; x < tileBounds.Width; x++, tileX++)
      {        
         tile = currentLevel->GetLayer(1).GetTile(tileX, tileY);
         if(tile != 0)
           tile->Draw((x* tileSize) - camOffset_x, (y*tileSize) - camOffset_y, *window);
      }
   }


I'm confused, am I doing something wrong (being blind to own mistakes) or is this behaviour normal for RenderWindow? Using one loop should naturally be faster in my opinion.


Notes:
   - Using references / pointers everywhere except with ints.
   - Layer 1 is full of Tiles (100x100), Layer 2 has an area of 26*20 tiles which fills screen.
   - Getters are simple methods, Tile->Draw only sets position and draws to window-parameter.
   - There's not much else going on in rendering code, few test objects here and there.
 
My computer is a netbook with Intel graphics & Pentium SU4100, crappy setup but it shouldn't be the issue here. Operating system Ubuntu, SFML version 2.0 latest snapshot. I should try using RenderTexture too, but it seems to give me segfaults, I read that it's a problem with Intel drivers.

Now excuse me if post is lacking some information, it's my first post here. So far I've been able to solve my problems with SFML but this goes beyond my understanding :)

edit: screenshot to clarify situation: http://bugi.oulu.fi/~zaih/example.png

There are grass tiles (layer 0) under water tiles (layer 1)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
[Solved] Drawing tiles, weird cpu usage
« Reply #1 on: November 27, 2011, 04:13:36 pm »
Do you have one texture for layer 1 and another for layer 0?
Laurent Gomila - SFML developer

zaih

  • Newbie
  • *
  • Posts: 3
    • View Profile
[Solved] Drawing tiles, weird cpu usage
« Reply #2 on: November 27, 2011, 04:27:54 pm »
I'm not sure if I understood your question correctly but something about this structure:

  - Layer is a class which holds Tiles in a two-dimension vector.
  - Level holds few layers ( in this case two )
  - Every tile has an own sprite, which uses texture from Texture manager
  - Texture manager returns references to concrete textures it holds.

So layers (tiles actually) should be able to use same textures with no problem, but in this case they use different textures (water / grass).


If that didn't answer your question, could you reformat it a bit?

Oh and I also tested what happens if I draw layer 0 twice in a same loop, no problems occured there.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
[Solved] Drawing tiles, weird cpu usage
« Reply #3 on: November 27, 2011, 04:59:36 pm »
Quote
in this case they use different textures

I think it answers my question.

If you do this:
Code: [Select]
loop
{
    draw(sprite with texture A)
    draw(sprite with texture B)
}

The graphics driver needs to change the current texture a huge amount of times -- and it is a costly operation.

But if you do this:
Code: [Select]
loop
    draw(sprite with texture A)

loop
    draw(sprite with texture B)

You only have 2 texture switches.
Laurent Gomila - SFML developer

zaih

  • Newbie
  • *
  • Posts: 3
    • View Profile
[Solved] Drawing tiles, weird cpu usage
« Reply #4 on: November 27, 2011, 05:59:41 pm »
Cheers Laurent for fast & clear replies. My knowledge of "what happens near hardware" is slacking a lot, so I didn't even think of this from gpu aspect.

I think I get it now, and this problem is solved in theory. I tried what happens if bottomlayer has 100 different textures next to each other. Drawing that alone while moving around the map made my processor struggle also, as expected according to your reply.

Now I think I must think some design issues before continuing this project. I haven't done tile-engine before, so I'm not familiar with basic problems related to it. I thought everything would be okay this way (having few layers, drawing them in order, drawing objects here and there and all would work), but obviously this will be way too heavy, unless layers are very simple, which makes the world look dull. In my opinion netbooks should be able to handle small 2d projects like this :)

I'll mark this thread solved and try to come up with some working solutions.

Thank you!