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

Author Topic: 15%-20% CPU usage when drawing a grid  (Read 3174 times)

0 Members and 1 Guest are viewing this topic.

Pacifico

  • Newbie
  • *
  • Posts: 4
    • View Profile
15%-20% CPU usage when drawing a grid
« on: February 05, 2014, 07:11:44 am »
Hello.

I decided to attempt a quick version of Conway's Game of Life to familiarize myself with JSFML. I noticed when simply drawing a grid of rectangles, my CPU usage will spike up to 15%-20% on my i5-3570K. Would anyone be able to tell me what I am doing wrong? This amount of CPU usage for a grid seems excessive, and I'm wondering if the draw calls are being performed by the CPU, instead of the GPU, or if they aren't being batched the way I imagine.

Here's the code I am using to reproduce the issue. If I add
window.setVerticalSyncEnabled(true);
to my code, the CPU usage will spike up to 25%-30%! I appreciate any help!

import org.jsfml.graphics.Color;
import org.jsfml.graphics.RectangleShape;
import org.jsfml.graphics.RenderWindow;
import org.jsfml.system.Vector2f;
import org.jsfml.window.VideoMode;
import org.jsfml.window.event.Event;

public class GameOfLife {
    private RenderWindow window;
    private RectangleShape rectangle;
    private final static int WIDTH = 64;
    private final static int HEIGHT = 48;
    private final static int SIZE = 10;

    public GameOfLife() {
        window = new RenderWindow(new VideoMode(640, 480), "Game of Life");
        window.setFramerateLimit(60);

        rectangle = new RectangleShape(new Vector2f(SIZE, SIZE));
        rectangle.setOutlineThickness(1);
        rectangle.setOutlineColor(Color.BLACK);
    }

    public void run() {
        while (window.isOpen()) {
            processEvents();
            update();
            render();
        }
    }

    private void processEvents() {
        for (Event event : window.pollEvents()) {
            switch (event.type) {
                case CLOSED:
                    window.close();
                    break;
            }
        }
    }

    private void update() {
    }

    private void render() {
        window.clear();

        for (int row = 0; row < HEIGHT; row++) {
            for (int column = 0; column < WIDTH; column++) {
                int x = column * SIZE;
                int y = row * SIZE;
                rectangle.setPosition(x, y);
                window.draw(rectangle);
            }
        }

        window.display();
    }

    public static void main(String[] args) {
        (new GameOfLife()).run();
    }
}
 

Pacifico

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: 15%-20% CPU usage when drawing a grid
« Reply #1 on: February 09, 2014, 10:01:50 pm »
Anyone?

FRex

  • Hero Member
  • *****
  • Posts: 1842
    • View Profile
    • My GitHub Page
    • Email
Re: 15%-20% CPU usage when drawing a grid
« Reply #2 on: February 09, 2014, 11:34:38 pm »
SFML always uses OpenGL and never batches anything, you should try to reduce the amount of draw calls. This applies to all languages.
ZipSavings, script to count rar/7z/zip savings: https://goo.gl/vvBj5M
LuaConsole: https://goo.gl/X4kRUk
FoxRaycaster: https://goo.gl/27nVS8
Small Games - Heart, Routing and Snek: https://goo.gl/15ZGWE https://goo.gl/k5gwWD https://goo.gl/4nKPnT
Botes - a notes app in Pascal: https://goo.gl/bzTqsi

eigenbom

  • Full Member
  • ***
  • Posts: 228
    • View Profile
Re: 15%-20% CPU usage when drawing a grid
« Reply #3 on: February 10, 2014, 02:16:19 am »
A vertex array should speed this up dramatically.

Pacifico

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: 15%-20% CPU usage when drawing a grid
« Reply #4 on: February 10, 2014, 02:40:58 am »
I appreciate the help! I was able to modify the example to use a vertex array, which greatly reduces the number times the render window calls draw. Here's an updated sample in case anyone else runs into a similar issue. My CPU usage when running the following code is usually less than 3%, much better than 15%-20%.

import org.jsfml.graphics.*;
import org.jsfml.system.Vector2f;
import org.jsfml.window.VideoMode;
import org.jsfml.window.event.Event;

public class VertexTest {
    private RenderWindow window;
    private VertexArray rectangles;
    private final static int WIDTH = 64;
    private final static int HEIGHT = 48;
    private final static int SIZE = 10;

    public VertexTest() {
        window = new RenderWindow(new VideoMode(640, 480), "Game of Life");
        window.setFramerateLimit(60);
        rectangles = new VertexArray(PrimitiveType.QUADS);
    }

    public void run() {
        while (window.isOpen()) {
            processEvents();
            update();
            render();
        }
    }

    private void processEvents() {
        for (Event event : window.pollEvents()) {
            switch (event.type) {
                case CLOSED:
                    window.close();
                    break;
            }
        }
    }

    private void update() {
        rectangles.clear();
        for (int row = 0; row < HEIGHT; row++) {
            for (int column = 0; column < WIDTH; column++) {
                int x = column * SIZE;
                int y = row * SIZE;

                // Create a one pixel border on the bottom and right sides
                // top-left
                rectangles.add(new Vertex(new Vector2f(x, y), Color.WHITE));
                // bottom-left
                rectangles.add(new Vertex(new Vector2f(x, y + SIZE - 1), Color.WHITE));
                // bottom-right
                rectangles.add(new Vertex(new Vector2f(x + SIZE - 1, y + SIZE - 1), Color.WHITE));
                // top-right
                rectangles.add(new Vertex(new Vector2f(x + SIZE - 1, y), Color.WHITE));
            }
        }
    }

    private void render() {
        window.clear();
        window.draw(rectangles);
        window.display();
    }

    public static void main(String[] args) {
        (new VertexTest()).run();
    }
}
 

pdinklag

  • Sr. Member
  • ****
  • Posts: 330
  • JSFML Developer
    • View Profile
    • JSFML Website
Re: 15%-20% CPU usage when drawing a grid
« Reply #5 on: February 12, 2014, 04:33:29 pm »
I'm not really sure why the rectangle approach would use that much CPU load, I will try this myself one of these days.

Anyway, this is a job for vertex arrays indeed. In that latest version of your code, if you call your "update()" function only when needed, it should approach 0% CPU load. There's no need to fill the vertex array with the same information in every frame, it's enough to do it when the application starts or something in the game field changes.

As for your VSync observation, yes, one is not supposed to use BOTH VSync and frame limiting, as they will get in the way of each other. This is also mentioned in the Javadoc.
JSFML - The Java binding to SFML.

Pacifico

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: 15%-20% CPU usage when drawing a grid
« Reply #6 on: February 16, 2014, 04:03:17 am »
I'm not really sure why the rectangle approach would use that much CPU load, I will try this myself one of these days.

I think it's like FRex said, too many draw calls per frame. In my original example, I was performing 3072 draw calls every frame. While that isn't a huge amount of calls, it sure doesn't beat one draw call with a vertex array. He's also right that this isn't specific to JSFML, as I was able to reproduce it with SFML.NET too.

Anyway, this is a job for vertex arrays indeed. In that latest version of your code, if you call your "update()" function only when needed, it should approach 0% CPU load. There's no need to fill the vertex array with the same information in every frame, it's enough to do it when the application starts or something in the game field changes.

You're right, doing that did drop the CPU usage to 0%.

I appreciate the feedback. I'm new to game/graphics programming, so there's definitely more for me to learn.