Noodalls input lag testing (unique method - games/controllers/etc) (updated last two years worth!)

I’ve spent some time comparing my results to displaylag.com’s results. I’ve actually reached out on twitter/facebook before but never heard back. In any event, if you compare his previous results
https://web.archive.org/web/20161203054902/http://www.displaylag.com/video-game-input-lag-database/
to mine, they seem to differ by a quite consistent amount on PS4.

USF4 X360 85 vs 57.4 (28ms difference)
USF4 PS4 89 vs 59 (30ms)
GGXrd PS4 89 vs 58 (31ms)
MKX PS4 105 vs 75 (30)
USF4 PS3 107 vs 77 (30ms)
KOFXIV Demo 107 vs 76 (31ms)
SFV 128 vs 88ms (30ms)
etc. etc.

The only one significantly different was Killer Instinct 81 vs 64ms (16ms). I don’t know why this one was the odd one out, as I’ve gone back and I get the same result.

Now, at this time he was using the XIM4 converter with a keyboard.

More recently, he has started testing with a LED and Brook UFB (same as me). When I compared the UMVC3 results.

X360 77ms vs 64ms (13ms difference)
X1 80ms vs 62ms (18ms)
PS4 89ms vs 102ms (13ms)

and if we compare the most recent MVCI PS4 88ms vs 102 ms (14ms difference)

So his results used to be fairly consistently 30ms slower than mine, now they are much closer to 1F. Presumably the XIM4 converter was adding a frame of lag then?

However, when you look at his current database, it appears there are results mixed together from old and new tests. Some of the difference probably comes from the rounding, but some I don’t think does.

e.g.

USF4 PS4 used to be 5.1F, now 4F
UMvC3 X360 used to be 4.6F now 4F
GGXrd Rev2 used to be 5.3F now 4F
MKXL used to be 6.3F now 5F
KOF XIV used to be 6.4F now 6F
UMvC3 PS4 used to be 6.1F now 6F
SFV used to be 7.3F now 7F

So comparing old results to new results, some are just .1F different, and others are 1.3F different.

To me it looks like some results are new but others old, and all have been rounded down (never up) to the nearest frame.

I get that PC testing is a pain for you with all the extra steps you go through. I read an old topic with more information on your testing methods and I know that it is very time consuming and is a labor of love. It is indeed very difficult to compare results between different methodologies, especially when they are poorly documented or filled with inconsistencies. I am just trying to find a middle ground between a limited set of results. Thank you for providing more information on input lag, there are very few sources remaining.

That said, there are some variations in your own past results, namely VF5:FS.

This one is interesting. So, everything on this thread is by the same method, whereas the results there were from an earlier way of testing. Essentially I waited until I worked out a lot of the flaws before starting this thread as a clean break. My point was, I haven’t mixed and matched results here.

But, for the longest time, I thought FS was a frame slower than Vanilla. Turns out the move I was using (Pai standing P) was a frame slower in VF5FS. Move selection is not mentioned but is quite important in checking input lag. I struggled with SFV for a long time using standing jab (my go to attack as it tends to animate the fastest) as often the animation on the first frame is not the same. It seems to blend depending on what part of the neutral stance Ryu was in, and seems to sometimes even skip the animation until the 2nd frame. Learning this, I went with his standing medium punch, which animates clearly and consistently on the first frame.

Another thing that comes up is command history. In most games there is a consistent relationship between when the command appears and when the animation begins. I assumed I could use this for all games. But, in SFV and now Tekken 7, there is variation. E.g. in Tekken for the last 5 games, probabably all the way back to Tekken 3 the command would appear one frame before the animation begins. In Tekken 7 it can appear before or on the first frame of animation. I’m not sure if this is just an unreal engine 4 quirk or not.

It is interesting that there are so many of these small variations. However, for whatever reason, Final Showdown feels slow to me to this day. I know they added startup to throws and other things, however the biggest discrepancy I have found was trying to do standing block after a blocked 2P. It feels really awkward as 2P was such an important part of Virtua Fighter and in combination with other additions it definitely makes the game feel heavier to control relative to other installments.

Displaylag have updated their results again. To now compare (difference in brackets).

GGXRD PS4 58.7 vs 70 (12ms, note I tested Rev2 while they tested Xrd, I haven’t retested Xrd but on previous tests it was the same as Rev 1/2)
USF4 PS4 59.1 vs 75 (15ms)
UMVC3 X360 64.4ms vs 77ms (13ms)
Injustice 2 PS4 91ms vs 92.4ms (2ms!)
MKXL PS4 75 vs 90ms (15ms)
DOA5LR PS4 75 vs 90ms (15ms)
KOFXIV 76.5ms vs 93ms (16.5ms)
TTT2 PS3 94 vs 100ms (6ms!)
SFV PS4 88.6ms vs 100ms (11ms)
UMVC3 PS4 89.1 vs 100ms (11ms)
MVCI PS4 88.8ms vs 102ms (13ms)
T7 PS4 120ms vs 128ms (8ms)

So now our results differ by between half to one whole frame (with Injustice 2 as a pretty big outlier.)

One thing that I had thought about, given that the screen updates from the top to the bottom, the different move used could potentially affect the result. For example, if you are looking at an animation change at the top of the screen, such as the life bar, it will occur almost 16ms ahead of an animation change at the bottom. And I’m not sure about video recording for the lighting up of the button, but I wonder if a similar issue may occur depending on whether the LED is at the top or the bottom of the image.

My method shouldn’t be affected by this.

https://youtu.be/3Ge6y5fEeTg

Video explaining my input lag tests for Tekken 7.

https://www.youtube.com/watch?v=jqwrbRPo3W4&t=40s

Digital foundry using my results (appropriately referenced).

Congrats!

May be now after 1.03 patch for T7 on PS4 needs some corrections and new tests?

https://www.youtube.com/watch?v=w22c7J868pE

Somebody asked for me to post my source code.

Spoiler

int button=0;
int set=1;
int mode=1;

int red=62;
int blue=63;
int red_button=64;
int blue_button=65;
int red_LED=66;
int blue_LED=67;

int red_on_done=0;
int red_off_done=0;
int blue_on_done=0;
int blue_off_done=0;

int x=0;
int setting=1;
unsigned long time1;
unsigned long time2;
unsigned long time3;
unsigned long time4;
unsigned long time5;
unsigned long time6;
unsigned long time7;

int long red_on=00000;
int long red_off=16666;
int long blue_on=00000;
int long blue_off=1000;
int long cycle = 500250;
int skip = 00000;

#include “SPI.h”
#include “Adafruit_GFX.h”
#include “Adafruit_ILI9341.h”
#include “Wire.h” // this is needed for FT6206
#include “Adafruit_FT6206.h”
// For the Adafruit shield, these are the default.
#define TFT_DC 9
#define TFT_CS 10
#define SD_CS 4
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
Adafruit_FT6206 ctp = Adafruit_FT6206();
int cs_pin=53;

void setup() {

pinMode(cs_pin,OUTPUT);

tft.begin();
ctp.begin();
tft.setTextColor(ILI9341_WHITE); tft.setTextSize(2);
tft.setRotation(0);
tft.fillScreen(ILI9341_BLUE);
tft.fillRect(0,140,120,120,ILI9341_RED);
tft.fillRect(120,140,120,120,ILI9341_BLUE);
tft.fillRect(0,250,240,120,ILI9341_BLACK);
tft.fillRect(0,0,240,140,ILI9341_BLACK);

tft.drawRect(0,0,40,70,ILI9341_WHITE);
tft.drawRect(40,0,40,70,ILI9341_WHITE);
tft.drawRect(80,0,40,70,ILI9341_WHITE);
tft.drawRect(120,0,40,70,ILI9341_WHITE);
tft.drawRect(160,0,40,70,ILI9341_WHITE);
tft.drawRect(200,0,40,70,ILI9341_WHITE);

tft.drawRect(0,70,40,70,ILI9341_WHITE);
tft.drawRect(40,70,40,70,ILI9341_WHITE);
tft.drawRect(80,70,40,70,ILI9341_WHITE);
tft.drawRect(120,70,40,70,ILI9341_WHITE);
tft.drawRect(160,70,40,70,ILI9341_WHITE);
tft.drawRect(200,70,40,70,ILI9341_WHITE);

//tft.drawRect(0,140,120,120,ILI9341_BLUE);
//tft.drawRect(0,60,120,60,ILI9341_BLUE);
//tft.drawRect(0,120,120,60,ILI9341_WHITE);

//tft.drawRect(120,0,120,60,ILI9341_RED);
//tft.drawRect(120,60,120,60,ILI9341_RED);
//tft.drawRect(120,120,120,60,ILI9341_WHITE);

pinMode(blue,OUTPUT);
pinMode(red,OUTPUT);
pinMode(red_button,OUTPUT);
pinMode(blue_button,OUTPUT);
pinMode(red_LED,OUTPUT);
pinMode(blue_LED,OUTPUT);
digitalWrite(red_button,HIGH);
digitalWrite(blue_button,HIGH);
digitalWrite(blue,HIGH);
digitalWrite(red,HIGH);
digitalWrite(red_LED,HIGH);
digitalWrite(blue_LED,HIGH);

tft.setCursor(1,141);
tft.print(“ON”);
tft.setCursor(1,171);
tft.print(red_on);

tft.setCursor(1,201);
tft.print(“OFF”);
tft.setCursor(1,231);
tft.print(red_off);

tft.setCursor(1,271);
tft.print(“CYCLE”);
tft.setCursor(1,301);
tft.print(cycle);

tft.setCursor(121,141);
tft.print(“ON”);
tft.setCursor(121,171);
tft.print(blue_on);

tft.setCursor(121,201);
tft.print(“OFF”);
tft.setCursor(121,231);
tft.print(blue_off);

tft.setCursor(121,271);
tft.print(“SKIP”);
tft.setCursor(121,301);
tft.print(skip);
}

void loop() {

if (mode==1){if ((time2)<(micros())){
time1=micros();skip=0;mode=2;}}

if(mode==2){

if ((micros()>time2+red_on) && red_on_done==0){time3=micros();digitalWrite(red_LED,HIGH);digitalWrite(red,LOW);digitalWrite(red_button,HIGH);red_on_done=1;}
if ((micros()>time2+blue_on) && blue_on_done==0){time4=micros();digitalWrite(blue_LED,HIGH);digitalWrite(blue,LOW);digitalWrite(blue_button,HIGH); blue_on_done=1;}
if ((micros()>time2+red_off) && red_off_done==0){time5=micros();digitalWrite(red_LED,LOW);digitalWrite(red,HIGH);digitalWrite(red_button,LOW);red_off_done=1;}
if ((micros()>time2+blue_off) && blue_off_done==0){time6=micros();digitalWrite(blue_LED,LOW);digitalWrite(blue,HIGH);digitalWrite(blue_button,LOW);blue_off_done=1;}

if(micros()>time2+60000){mode=3;}

}

if(mode==3){

if (ctp.touched())
{
TS_Point p = ctp.getPoint(); // x = 240, y= 320

if(p.x>200){if(button==0){
if(p.y>250 && p.y>180){set++;}
if(p.y<250){set–;}
if(set<1){set=6;}
if(set>6){set=1;}
tft.setCursor(2,30);tft.fillRect(2,30,20,20,ILI9341_BLACK);tft.print(set);}}

if(p.y>180){
if(button==0){x=0;
if(p.x>0 && p.x<40 && p.y>180 && p.y<250){x=x-1;}
if(p.x>0 && p.x<40 && p.y>250 && p.y<320){x=x+1;}

if(p.x>40 && p.x<80 && p.y>180 && p.y<250){x=x-10;}
if(p.x>40 && p.x<80 && p.y>250 && p.y<320){x=x+10;}

if(p.x>80 && p.x<120 & p.y>180 && p.y<250){x=x-100;}
if(p.x>80 && p.x<120 & p.y>250 && p.y<320){x=x+100;}

if(p.x>120 && p.x<160 & p.y>180 && p.y<250){x=x-1000;}
if(p.x>120 && p.x<160 & p.y>250 && p.y<320){x=x+1000;}

if(p.x>160 && p.x<200 & p.y>180 && p.y<250){x=x-10000;}
if(p.x>160 && p.x<200 & p.y>250 && p.y<320){x=x+10000;}

if (set==1){red_on=red_on+x;
if (red_on>50000){red_on=50000;}
if (red_on<0){red_on=0;}
tft.fillRect(0,171,120,20,ILI9341_RED);
tft.setCursor(1,171);
tft.print(red_on);}

if (set==2){ red_off=red_off+x;
if (red_off>50000){red_off=50000;}
if (red_off<0){red_off=0;}
tft.fillRect(0,231,120,20,ILI9341_RED);
tft.setCursor(1,231);
tft.print(red_off);}

if(set==3){ cycle=cycle+x;
if (cycle>1999999){cycle=1999999;}
if (cycle<100000){cycle=100000;}
tft.fillRect(1,301,110,20,ILI9341_BLACK);
tft.setCursor(1,301);
tft.print(cycle);}

if (set==4){blue_on=blue_on+x;
if (blue_on>50000){blue_on=50000;}
if (blue_on<0){blue_on=0000;}
tft.fillRect(121,171,120,20,ILI9341_BLUE);
tft.setCursor(121,171);
tft.print(blue_on);}

if(set==5){blue_off=blue_off+x;
if (blue_off>50000){blue_off=50000;}
if (blue_off<0){blue_off=0000;}
tft.fillRect(121,231,120,20,ILI9341_BLUE);
tft.setCursor(121,231);
tft.print(blue_off);}

if(set==6){skip=x;
tft.fillRect(121,301,120,20,ILI9341_BLACK);
tft.setCursor(121,301);
tft.print(skip); }

button=1;
tft.fillRect(2,100,130,20,ILI9341_BLACK);tft.setCursor(2,100);
tft.print(time5-time3);//tft.print("-");//tft.print(time4-time3);
}}}

else

{button=0;}
red_on_done=0;
red_off_done=0;
blue_on_done=0;
blue_off_done=0;
time2=time1+cycle+skip;mode=1;}

}

First and foremost, thank you a lot for your hard work, noodalls. It’s great that there are curious mind like yours willing to put in the work so we can all benefit from the results of your research.

Now that is out of the way: I’m still a complete layman, and I have some questions on this topic.

Are you familiar with Teyah’s work? He also tested sticks, pcbs and controllers for input lag. Here are his results:
http://www.teyah.net/sticklag/results.html

Let’s take the HRAPV4 as an example. His results listed it as having 4.80ms of lag, while yours puts it at 48ms. His ps360+ results listed it as having no lag at all on version 1.65 (and upwards, I presume). Yours listed it at 44.4ms for version 1.66.

Here is his methodology:
http://www.teyah.net/sticklag/overview.html

What explains the discrepancy in your results? It’s a discrepancy of over 2 frames (~33.3ms) in both cases. Being a complete layman on the subject, I just see the very different numbers and get confused. Is it due to a difference in the testing method or something like that?

Again, my gratitude to both of you for you work (I’m fairly certain Teyah has a SRK account); I’m merely curious and very interested on this topic. Please excuse me if my questions are stupid.

Put simply, I have posted the results for the controller plus game put together.

In all of my tests for different controllers (except for the WiiU/Wii and in the future possibly the switch) I used Blazblue (normally Blazblue CPE, but BBCS for x360 as that is the title that I own). Assuming that the game doesn’t respond differently to different controllers, then the only difference between different tests should be due to the controller.

Thank you for reply, man.

By the way, I also watched a vid on network & input delay, recently. It seemed to me modern games are maybe purposefully introducing native game lag so as to make offline and online play feel about the same.

This was the vid:
https://www.youtube.com/watch?v=CBuNqCtHv9I

If this is true, do you think older era fighting games (SNES to ps2) had much lower native lag? Do you plan on ever testing these older fighting games to compare, if the additional time and money investment is not a problem for you?

Quick question, Noodalls when doing your testing do you have the ‘sharp’ setting on your monitors set to 0/off?

Most people have any kind of post processing off, or at least as much as possible.
I think its best to leave the sharp setting off.

Yeah, Noodalls probably has it off when doing his testing but a lot of people think the sharp setting is the same as the sharp setting on a CRT without realizing it’s just more post processing.

CRT is a different beast as it’s all analog. And there is very little to no delay in analog signals. Many fans of Retro gaming still rely on CRTs for this reason.
Like their is a way to intentionally delay a signal in analog circuitry, its used in live broadcasts to allow time to put in censorship beeps to cover up fowl language.
But nothing like that in a CRT Display.

In Digital, signals need time to process. And the more tasks you put on the longer that signal is going to get processed.
Its why for the longest time Modern Console players used Ether Cheaper HD TVs or PC monitors for game play. The newer wave of HDTVs finally have the processing time to negate some of that lag time.

The way my setup is the monitor settings should have no effect on the results.

So, the way my system works is to interrupt one or both of the blue and red components of component cable. This doesn’t work in the same way for composite signals when I’ve tried it, so I can’t simply test on old systems. It would be easy enough to apply my technique to the audio lines, however every time I’ve tried this there is poor sync between the audio and video with various capture devices, so I’ve given up on that for now.

I tested several versions of SF2 Super Turbo. A generation after the PS2.

NKI tested Capcom Classics collection on the PS2 as a frame slower than the Dreamcast.

The Dreamcast is closer to the native arcade hardware, PS2 uses oddly exotic hardware.

Also did you use a Phat or Slim PS2, as they have some major serious hardware revisions?

The older Phat PS2 consoles did more in hardware and has dedicated hardware for rendering and effects.
PS2 Slim has a more powerful CPU and more Ram but did alot of the same rendering and effects in software that been written to a chip on the main logic board.