Questions about an efficient SHM game loop

Philip Bizimis bizimisphilip at gmail.com
Wed May 8 11:49:51 UTC 2024


I am currently working on a small Wayland Snake game to
learn about Wayland and game development. I am using SHM
double buffers for rendering.

My main game loop has two parts that run at different speeds so
that I can have a constant game speed independent of variable
FPS (based on https://dewitters.com/dewitters-gameloop):
```
game_loop() {
    while(1) {
        // wl_display_dispatch
        while(at least X times a sec) {
            update();
        }
        render();
    }
```
In my case, there could be several game updates before a frame
is rendered. But there could also be hundreds of frames between
game updates if the hardware is good enough.

Currently, the game works fine if I use wl_display_dispatch.
However, I feel like for optimal performance a blocking call does not
make sense. Also, I would think that I would only want to process
events that I need for the updating in the update loop, and not only
once in the main loop. So my plan is to have something like:
```
game_loop() {
    while(1) {

        while(at least X times a sec) {
            // receive all input changes
            update(); // update game state based on
                           // LEFT RIGHT UP DOWN
        }
        // render where the snake is currently
        render();
    }
```
My render function at the moment looks like:
```
void render(...) {
  struct buffer *free_buffer = find_free_buffer(...);
  // set to available with a buffer_release callback

  if (free_buffer != NULL) {
    fill_frame(free_buffer->shm_data, state);
    render_frame(state->wl_surface, free_buffer);
  }
}
```
My update function does not interact with Wayland except using the
last pressed key as the direction of the snake.

I have attempted the following approaches without success:
```
game_loop() {
    while(1) {
       wl_display_dispatch_pending(d);
        while(at least X times a sec) {
            update();
        }
        render();
        wl_display_flush(d);
    }
```
```
  struct pollfd pollfds[] = {
      {
          .fd = wl_display_get_fd(state->wl_display),
          .events = POLLIN,
      },
  };

  while (1) {
    if (pollfds[0].revents & POLLIN) { // never true
        wl_display_dispatch();
    ...
```
Both compiled but did not produce any client window.
I would greatly appreciate your help. I have spent a lot of hours
on this and seem to have hit a wall. In case you would like to take
a look at the whole code: github.com/pbizimis/snake

Thank you so much and have a great day,
Philip


More information about the wayland-devel mailing list