Seriously severe input delay on AL5.0.10
Maurício Gomes

I made this sample program that demonstrates that Allegro has some serious input delay, I tested it on Windows (no other OS nearby now, sorry :( )

You can play "normally" and you will notice that the controls are not tight as they should (for a action game at least), but you can REALLY see the effect if you just press arrow keys in random directions as fast as you can (like if you was making a fighting game input), and then just watch the screen, the longer you made your "combo", the longer the ship will move on its own.

EDIT: Fixed a bug in the example code that Elias noticed.

1//libraries 2#include <stdio.h> 3#include <allegro5/allegro.h> 4#include <allegro5/allegro_primitives.h> 5 6//project headers 7#include "gamelogic.h" 8 9const int PLAYFIELD_W = 1280; 10const int PLAYFIELD_H = 720; 11#define UPDATE_TIME 1.0/125 //1 second divided by 125 frames per second, this is to guarantee a round milisecond speed 12 13ALLEGRO_KEYBOARD_STATE keyboardState; 14 15int main() 16{ 17 ALLEGRO_MONITOR_INFO monitorInformation; 18 ALLEGRO_DISPLAY *display; 19 ALLEGRO_EVENT_QUEUE *events; 20 ALLEGRO_TIMER *updateTimer; 21 int screenWidth; 22 int screenHeight; 23 int counter; 24 25 //////////////////////////// 26 //Setup phase starts here // 27 //////////////////////////// 28 if(!al_init()) 29 { 30 fprintf(stderr, "Failure loading Allegro\n"); //should not happen, but who knows... 31 return 1; 32 } 33 34 //now we create our display 35 counter = 0; 36 while(al_get_monitor_info(counter, &monitorInformation)) //this function returns false when it fails 37 { 38 if(monitorInformation.x1 == 0 && monitorInformation.x2 != 0) break; //we found what we wanted 39 ++counter; 40 } 41 42 screenWidth = monitorInformation.x2 - monitorInformation.x1; 43 screenHeight = monitorInformation.y2 - monitorInformation.y1; 44 45 al_set_new_display_flags(ALLEGRO_FULLSCREEN); 46 al_set_new_display_option(ALLEGRO_VSYNC, 1, ALLEGRO_SUGGEST); 47 display = al_create_display(screenWidth, screenHeight); 48 if(!display) 49 { 50 fprintf(stderr, "Failure setting up the display\n"); 51 return 2; 52 } 53 54 if(!al_install_keyboard()) 55 { 56 fprintf(stderr, "Failure installing keyboard\n"); 57 al_destroy_display(display); 58 return 3; 59 } 60 61 if(!al_init_primitives_addon()) 62 { 63 fprintf(stderr, "Failure loading primitives addon\n"); 64 al_destroy_display(display); 65 return 4; 66 } 67 68 updateTimer = al_create_timer(UPDATE_TIME); 69 70 events = al_create_event_queue(); 71 if(!events) 72 { 73 fprintf(stderr, "Somehow there was a failure creating a event queue, this really should not have happened\n"); 74 al_destroy_display(display); 75 return 5; 76 } 77 78 al_register_event_source(events, al_get_display_event_source(display)); 79 al_register_event_source(events, al_get_timer_event_source(updateTimer)); 80 81 /////////////////////////// 82 //Setup phase ended here // 83 /////////////////////////// 84 85 al_start_timer(updateTimer); 86 87 double playerX = 20.0; 88 double playerY = (double)PLAYFIELD_H/2.0; 89 90 bool redraw = false; 91 92 while(true) 93 { 94 static ALLEGRO_EVENT event; 95 al_wait_for_event(events, &event); 96 97 if(event.type == ALLEGRO_EVENT_TIMER) 98 { 99 //updateGame(); 100 al_get_keyboard_state(&keyboardState); 101 if(al_key_down(&keyboardState, ALLEGRO_KEY_DOWN)) 102 { 103 playerY+=10; 104 } 105 if(al_key_down(&keyboardState, ALLEGRO_KEY_UP)) 106 { 107 playerY+=-10; 108 } 109 if(al_key_down(&keyboardState, ALLEGRO_KEY_LEFT)) 110 { 111 playerX+=-10; 112 } 113 if(al_key_down(&keyboardState, ALLEGRO_KEY_RIGHT)) 114 { 115 playerX+=10; 116 } 117 redraw = true; 118 } 119 else if(event.type == ALLEGRO_EVENT_DISPLAY_CLOSE) 120 { 121 break; 122 } 123 124 if(redraw && al_is_event_queue_empty(events)) 125 { 126 redraw = false; 127 al_clear_to_color(al_map_rgb(0,0,0)); 128 al_draw_filled_triangle(playerX-10, playerY-10, playerX+10, playerY, playerX-10, playerY+10, al_map_rgb(255, 255, 255)); 129 al_flip_display(); 130 } 131 } 132 133 134 printf("hello world!\n"); 135 136 137 /////////////////////////////// 138 // Cleanup phase starts here // 139 /////////////////////////////// 140 al_destroy_timer(updateTimer); 141 al_destroy_event_queue(events); 142 al_destroy_display(display); 143 return 0; 144}

Bruce Perry

You should put brackets around the value of UPDATE_TIME, just in case it ever trips you up.

As for the delay problem, what happens if you attach the keyboard event source to that event queue? (Obviously your existing code would ignore the new events you get, but I wonder if it will cause some voodoo changes inside Allegro.)


I THINK that with your code you're only checking for input change every time your timer fires up an event, so you're processing only the last event in the Keyboard state when this happens and not the Keyboard events themselves.

So basically, what Bruce said....changing your code accordingly.

Maurício Gomes

pkrcel that was my intention all along.

But what I got to see instead is a accumulation of keyboard input, that keeps acting on the game even after you let them go.

Source delving by me and others suggest that is because of misuse of WinAPI, for example every time a key is pressed it calls GetKeyboardState, plus GetKeyState three times. And in WinAPI itself it alread warns that those functions have delays.


I have reproduced this delay on my system, and it stems from some odd design choices in the D3D backend as well as keyboard handling. I have created a proof-of-concept set of changes to both to try to eliminate this lag as much as possible. It requires a lot more testing before I feel comfortable committing it to Allegro proper.

That said, attached is a version of the program in the OP with the changed Allegro alongside it, as well as the patch to Allegro (relative to 5.1) just so you can see what I did. I'm not sure it can get much better than that, but even going as far as I did has basically eliminated the lag for me. See if it does so on your system as well.


I should note, when you run speeder.exe you can pass in any argument to cause it to launch in fullscreen, if you want. Also, the allegro5.cfg alongside it can be used to force it into OpenGL mode.


The diff wasn't quite right. Fixed it.

Maurício Gomes

SiegeLord whatever you did, it worked here. I think I don't see any delay on this test exe


pkrcel that was my intention all along.

Yeah, now that I took more time to look at it, I understand the underlying desing...I misunderstood your description of the problem.


I like the patch, also the UNICODE part. I think this also will fix - for example al_set_window_title will work under Windows when the string contains non-ASCII letters.


Ok, so fixing the keyboard is turning out to be very difficult. The issue is that Allegro emits ALLEGRO_EVENT_CHAR for both printable characters and for other keys. The "proper" and fast way of handling input on Windows uses WM_CHAR to do the unicode characters... unfortunately Windows only sends WM_CHAR for printable characters, e.g. it won't send them for arrow keys and other such non-character keys. It is turning out to be very hard to not send superfluous ALLEGRO_EVENT_CHAR events. E.g. if you use the US-international keyboard you can press Shift+6 followed by an e to get an ê. Using WM_CHAR and my best attempt you will get an extra ALLEGRO_EVENT_CHAR when you do the Shift+6.

Anyway, the keyboard wasn't really the major component of this delay, rather it was the display loss checking code. Attached is the patch and binaries of the code that only fixes that (and enables unicode along the way). Please check it to see if it has appreciable input lag (maybe compare it with the binary in my earlier post).


Does ALLEGRO_EVENT_CHAR work correctly for shift+6+e right now?


Yes. The only issue with the current approach is that it is supposedly laggy (I think I can perceive it, but it's hard to tell) and I also noted that it doesn't work with IME... i.e. if you try to enter Chinese characters using IME, the little IME window won't show up (I haven't determined what part of my work handles the IME window... if it's just TranslateMessage, then I could put it in without actually handling WM_CHAR's).

Maurício Gomes

Great work SiegeLord :)

The lag is not random anymore (random lag is TERRIBLE) and is now 1 frame.

Not zero yet... but good enough for most games and players I guess.

Edgar Reynaldo

Out of curiosity, how are you measuring the lag?


Just perceptually. I guess I could look at the original timestamp of the MSG structure and compare it to when we emit the Allegro event.

EDIT: I tried it with this code: printf("Lag %ld\n", GetTickCount() - GetMessageTime()); at the spot where the keyboard events are emitted, and it showed a reduction from as much as 400 ms to 0 ms with an occasional 16 ms.

EDIT2: Committed the above patch.

Thread #613809. Printed from