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

Author Topic: Pushing everything to a VertexArray each frame  (Read 8414 times)

0 Members and 1 Guest are viewing this topic.

AbelToy

  • Newbie
  • *
  • Posts: 14
    • View Profile
    • AbelToy.com
    • Email
Pushing everything to a VertexArray each frame
« on: June 14, 2014, 07:46:19 pm »
So the method I'm using for rendering, is I have all these Images and Tilemaps and stuff I've written. Most of them work using vertices, and I have a BatchManager that will batch everything batchable into the same VertexArray (that is, everything that has the same texture, blendmode, shader, etc.)

Thing is, I've noticed this is a bit cpu-expensive. Clearing all the VertexArrays and pushing everything to them each frame seems to be a bit of a performance issue.

This is written using C# by the way, just to clarify.

Am I doing it terribly wrong? Should I just stick to using SFML's sprites and stuff that simply don't use batching (and just batch Tilemap or Particles)? Any tips on how to improve performance?

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Pushing everything to a VertexArray each frame
« Reply #1 on: June 14, 2014, 07:52:57 pm »
As with any "which is faster" question, the answer is: try it both ways and see what happens.

For how to improve performance, the answer is run your code under a profiler and see what it tells you.

Still, my impression is that sprite batching is primarily meant for things which will always be in the same batch every frame no matter what (like tilemaps and particles, as you said), so that you can just use a VertexArray instead of several Sprites from the get-go.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Pushing everything to a VertexArray each frame
« Reply #2 on: June 14, 2014, 07:53:35 pm »
Thing is, I've noticed this is a bit cpu-expensive. Clearing all the VertexArrays and pushing everything to them each frame seems to be a bit of a performance issue.
"A bit" and "seems"? So you have not measured it? :P

It would be nice to know exactly what is slow before giving concrete advice.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

AbelToy

  • Newbie
  • *
  • Posts: 14
    • View Profile
    • AbelToy.com
    • Email
Re: Pushing everything to a VertexArray each frame
« Reply #3 on: June 14, 2014, 08:30:04 pm »
I know it's a performance hit because the game uses quite a bit of CPU power.

The spike happens when opening the game. It goes from 1% to 20~30%: http://puu.sh/9tp7B/745a34a0b5.png

What kind of tests would you write to measure how much processing power it requires, and compared to what?

I know using just SFML's sprites would improve CPU performance, but how do I measure the GPU hit?

I was just asking in case someone faced a similar issue, or if someone had some tips on how to better handle sprite batching and such.

I'm new to programming for both the GPU and the CPU, as I mainly used AS3 before and I only had to worry about the CPU. I don't know what best practises are there for graphics programming that are easy both on the CPU vs. the GPU.

Not sure how to balance draw calls vs cpu power and such.

I have some ideas already (such as just draw the tilemaps directly instead of copying the huge vertexarray to another one each frame), but I just wanted to know if any of you had some ideas...
« Last Edit: June 14, 2014, 08:31:37 pm by AbelToy »

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Pushing everything to a VertexArray each frame
« Reply #4 on: June 14, 2014, 08:47:54 pm »
Don't use the CPU usage to measure your game's performance.  Get a real profiler so you can see how much actual time you spend in every function.  This will include some indirect information about GPU performance as well, though I don't know nearly as much about that.

The general thing you need to know is that there are very few general rules for CPU vs GPU stuff.  For some programs the bottleneck will be in the CPU, for others it'll be the GPU.  There really is no substitute for learning how to test and measure your individual program to see where your personal bottlenecks lie.

The main rule that does exist is that anything the GPU is specifically designed to do, it can probably do faster than the CPU.  So if you want to manipulate images, you're usually better off using GPU features like drawing to an sf::RenderTexture than you are editing the pixels of an sf::Image.

AbelToy

  • Newbie
  • *
  • Posts: 14
    • View Profile
    • AbelToy.com
    • Email
Re: Pushing everything to a VertexArray each frame
« Reply #5 on: June 14, 2014, 09:16:18 pm »
I ran Visual Studio 2013's profiler on my code.

The bottleneck seems to be a call to RenderTexture.clear(), that's done once per frame (and the one that clears the screen too). Weird. Is that usual?

The second bottleneck is accessing the SortedDictionary where I store the layers. Why is accessing a property so expensive? I don't understand...

Also, apparently it gives out no information about gpu performance. Sorry, I'm really new to profiling. What should I do? :(

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Pushing everything to a VertexArray each frame
« Reply #6 on: June 14, 2014, 09:32:01 pm »
tl;dr Try changing things and see if it gets faster or slower.

I haven't done any GPU-related profiling myself (I honestly don't know if proper "GPU profiling" is even possible) so you're probably better off Googling or waiting for a smarter person to post in here, but here's my guess: Because OpenGL is an asynchronus API, when you do things like draw() to a rendertexture the actual drawing may not happen immediately, and certain functions like clear() or display() may have to "block" if the GPU isn't done yet.  So my largely uneducated guess is you have a GPU bottleneck.  See what happens if you comment out a bunch of your GPU operations.

SortedDictionary would be a C#-specific issue, and I'm a C++ programmer, but I think this should help get you started on figuring that one out: https://stackoverflow.com/questions/935621/whats-the-difference-between-sortedlist-and-sorteddictionary  To me layers sounds more like a list than a tree, so see what happens if you try some other data structures.
« Last Edit: June 14, 2014, 09:35:40 pm by Ixrec »

AbelToy

  • Newbie
  • *
  • Posts: 14
    • View Profile
    • AbelToy.com
    • Email
Re: Pushing everything to a VertexArray each frame
« Reply #7 on: June 14, 2014, 09:53:05 pm »
Mhm... I see...

Actually I need to use layers using a SortedDictionary because of the way it works. Layers are an array that contain the entities.

I just don't understand why the bottleneck is just accessing the property itself (http://puu.sh/9tw2z/eac5d9b62d.png).



EDIT: I just tested a simple project that only clears the window and displays it each frame. 13% CPU. The additional RenderTexture is the other 13% that builds up to the 26%.

What the fuck? Why just calling RenderTexture's Clear method so performance intensive?



EDIT2: Ok, further testing done. The problem was I wasn't limiting the framerate. That's why it was so intensive, it just cleared the screen a lot. Will continue testing.
« Last Edit: June 14, 2014, 10:16:22 pm by AbelToy »

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Pushing everything to a VertexArray each frame
« Reply #8 on: June 14, 2014, 10:02:55 pm »
As always we need a complete and minimal example to make sure you are doing things correctly.
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

AbelToy

  • Newbie
  • *
  • Posts: 14
    • View Profile
    • AbelToy.com
    • Email
Re: Pushing everything to a VertexArray each frame
« Reply #9 on: June 14, 2014, 10:17:15 pm »
So, apparently VSync doesn't work the same way SetFramerateLimit does. If I set the framerate limit to 60, I get normal CPU usage. If I set VSync to true, I still get crazy framerate issues because all gets drawn so many times?

@zsbzsb: the problem is with the infrastructure though, so the minimal example would still need quite a few files and such. Is that ok?



EDIT: So yeah, setFramerateLimit seems to fix the issue (while VSync just does... nothing? wtf?). Now it's much better, wastes a lot less CPU and the computer fans don't make so much noise.

I think I'll keep the current method I'm using, while testing it further and improving it a bit (such as rendering tilemaps directly instead of batching them with the rest, only rendering the stuff on screen, etc.).

Thank you guys!
« Last Edit: June 14, 2014, 10:24:51 pm by AbelToy »

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Pushing everything to a VertexArray each frame
« Reply #10 on: June 15, 2014, 11:01:29 am »
@zsbzsb: the problem is with the infrastructure though, so the minimal example would still need quite a few files and such. Is that ok?
It seems to be solved, but... What infrastructure? I thought the problem was your dictionary and the clear() calls, why can't they be tested within a single class?

So, apparently VSync doesn't work the same way SetFramerateLimit does.
The framerate limit is just a clock-based approximation of the specified framerate; Display() waits as long as it needs. Vertical Synchronization means that the rendering is synchronized with the monitor's update rate -- it needn't be 60Hz, and can depend on graphics driver settings. So if you globally enforce disabled VSync, SFML can't use it.
« Last Edit: June 15, 2014, 11:03:19 am by Nexus »
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development: