Utilizator:
Parola:
Am uitat parola... | Cont nou!


Articole Resurse Echipe Competiții Proiecte Forum DevBlogs Locuri de muncă GDROMag Issue#1 GDROCon 2007

 
Forum » Programare » Altele » Input latency cu VSync on




Pagina 1 din 2 [ 1 | 2 ]

Mesaj Info autor
    Postat la 05 Feb 2009 20:11:15    Subiect: Input latency cu VSync on
Deliverance info:

Deliverance:

Am intampinat problema asta recent si nu am idee cum as putea sa o rezolv. Pe de o parte VSync elimina "tearing" dar apelul de swapbuffers fiind in acelasi thread cu cel al tratarii inputului va *MARI timpul de raspuns pentru inputul primit. O rezolvare ar fi sa dezactivez VSync si sa obtin un framerate destul de mare astfel incat latenta pentru input sa fie foarte mica. Ma intreb cum altfel se descurca lumea cu situatia asta. Very Happy

Ultima editare efectuată de Deliverance pe 05 Feb 2009 20:33:05; 1 editări în total


Status:
Înregistrat pe:
13 Oct 2006 10:05:37
Vârsta: 25 ani
Mesaje: 253
Locatie: Iasi , Romania
Programator

 
    Postat la 06 Feb 2009 07:53:09    Subiect: < fara subiect >
raicuandi info:

raicuandi:

Pai nush, eu am un 8600 si majoritatea jocurilor nu-mi ajung la 60FPS oricum.
La 60, latenta maxima de cand ai apasat un buton si cand a prins jocul o sa fie 16ms. Majoritatea monitoarelor merg la 60Hz.
Paremi-se ca Windows nu te lasa sa verifici mesajele din queueul altui thread, dar nu mai stiu sigur.

Method 2: Move Your Mouse Pointer
If you move your mouse pointer continuously while the data is being returned to Microsoft Excel, the query may not fail. Do not stop moving the mouse until all the data has been returned to Microsoft Excel.


Status:
Înregistrat pe:
24 Mar 2007 21:02:40
Vârsta: 22 ani
Mesaje: 514
Locatie: Adelaide, Australia
Programator

 
    Postat la 06 Feb 2009 11:03:53    Subiect: < fara subiect >
Dark info:

Dark:

Ce fel de joc faci de ti se pare mult sa ai 50-60 de milisecunde de lag? Daca nu faci vreun FPS hardcore pentru competitii pro, cred ca te agiti degeaba. Gindeste-te ca Soul Calibur merge la 60 de fps si e culmea jocurilor de twitch.

Oricum, vezi aici.

LE:

raicuandi a scris:


La 60, latenta maxima de cand ai apasat un buton si cand a prins jocul o sa fie 16ms


Latenta de cind apesi pina se prinde jocul nu conteaza, conteaza cit dureaza de cind apesi pina se vede pe ecran efectul, ceea ce n-are cum sa fie 16 ms la 60 de fps din diverse motive explicate in link-ul de mai sus.

Ultima editare efectuată de Dark pe 06 Feb 2009 11:06:49; 1 editări în total

"Am crezut ca esti ceva mai avansat" - Nekitu, 2008 A.D.
Autobaza


Status:
Înregistrat pe:
12 May 2007 20:12:30
Vârsta: ? ani
Mesaje: 740
Locatie:
Programator

 
    Postat la 06 Feb 2009 12:28:38    Subiect: < fara subiect >
raicuandi info:

raicuandi:

Wow e mult mai mare decat ma asteptam. Bine de stiut!

Method 2: Move Your Mouse Pointer
If you move your mouse pointer continuously while the data is being returned to Microsoft Excel, the query may not fail. Do not stop moving the mouse until all the data has been returned to Microsoft Excel.


Status:
Înregistrat pe:
24 Mar 2007 21:02:40
Vârsta: 22 ani
Mesaje: 514
Locatie: Adelaide, Australia
Programator

 
    Postat la 06 Feb 2009 15:10:48    Subiect: Re:
Deliverance info:

Deliverance:

Dark a scris:

Ce fel de joc faci de ti se pare mult sa ai 50-60 de milisecunde de lag? Daca nu faci vreun FPS hardcore pentru competitii pro, cred ca te agiti degeaba. Gindeste-te ca Soul Calibur merge la 60 de fps si e culmea jocurilor de twitch.

Oricum, vezi aici.

LE:

raicuandi a scris:


La 60, latenta maxima de cand ai apasat un buton si cand a prins jocul o sa fie 16ms


Latenta de cind apesi pina se prinde jocul nu conteaza, conteaza cit dureaza de cind apesi pina se vede pe ecran efectul, ceea ce n-are cum sa fie 16 ms la 60 de fps din diverse motive explicate in link-ul de mai sus.


Este vorba de o clona de breakout si pare ciudat cand misti mouseul repede(se observa un delay). Daca dezactivez VSync se misca ok padul Very Happy

Ultima editare efectuată de Deliverance pe 06 Feb 2009 15:15:06; 1 editări în total


Status:
Înregistrat pe:
13 Oct 2006 10:05:37
Vârsta: 25 ani
Mesaje: 253
Locatie: Iasi , Romania
Programator

 
    Postat la 06 Feb 2009 15:44:07    Subiect: < fara subiect >
Dark info:

Dark:

Cum updatezi pozitia pad-ului? Faci diferenta intre pozitia curenta a mouse-ului si pozitia in frame-ul anterior, dupa care aduni valoarea asta la x-ul pad-ului?

Epic Pong merge cu VSync pus tot timpul si nu sufera de lag din cauza asta.

"Am crezut ca esti ceva mai avansat" - Nekitu, 2008 A.D.
Autobaza


Status:
Înregistrat pe:
12 May 2007 20:12:30
Vârsta: ? ani
Mesaje: 740
Locatie:
Programator

 
    Postat la 06 Feb 2009 16:15:36    Subiect: Re:
Deliverance info:

Deliverance:

Dark a scris:

Cum updatezi pozitia pad-ului? Faci diferenta intre pozitia curenta a mouse-ului si pozitia in frame-ul anterior, dupa care aduni valoarea asta la x-ul pad-ului?

Epic Pong merge cu VSync pus tot timpul si nu sufera de lag din cauza asta.


Da, asa fac Smile. Diferenta intre pozitia mouseului acum - pozitia mouseului la frameul anterior si apoi plasez mouseul in centrul ecranului.

EDIT: am downloadat din nou Epic Pong si am dezactivat VSync din NVidia control panel. Pad-ul meu se misca okay dar bila merge prea repede, la fel si padul pentru AI. Cu VSync on nu intampin probleme.

EDIT2: Poate e de folos: am un intel pentium quadcore la 2.4ghz si GF9600GT

EDIT3: Asa arata mainloop-ul

Cod sursă:

// Main loop
glfwSwapInterval(1); // Turn VSync on if supported
while( isRunning )
{
    // UPDATE

    float amount = 1.0f / 200.0f;    
    static float accumulator = 0.0f;
    accumulator += timer.GetTime();
    timer.Reset();    
                
    while (accumulator >= amount)
    {    
        glfwPollEvents();

        int x,y;
        glfwGetMousePos( &x, &y );

        MouseMoveWrapper(x, y);
        
        CheckAndCallMousePressWrapper();

        states.back()->Update(amount);        
    
        accumulator -= amount;
    }
        
    // RENDER

    Render();            
}

 

Ultima editare efectuată de Deliverance pe 06 Feb 2009 17:16:41; 5 editări în total


Status:
Înregistrat pe:
13 Oct 2006 10:05:37
Vârsta: 25 ani
Mesaje: 253
Locatie: Iasi , Romania
Programator

 
    Postat la 06 Feb 2009 18:24:27    Subiect: < fara subiect >
Dark info:

Dark:

Epic Pong face timing cu timeGetTime(), care are rezolutie proasta, deci daca scoti vsync-ul si-l lasi sa mearga cu jdemii de FPS, toate calculele care implica timp se duc pe copca. Aveam si o varianta care folosea QPF, dar n-am pus-o din cauza ca respectiva functie are probleme pe CPU-uri facute de incompetenti (cum ar fi AMD). Oricum, daca pui QPF si scoti vsync o sa vezi ca nu apare lag, ba din contra, e mai putin "smooth" pentru ca fluctueaza fps-ul.

De ce faci chestia aia cu acumulatorul acolo? Cind ai vsync, pentru fiecare frame pictat o sa rulezi input-ul de 3 sau 4 ori, iar cind n-ai, o sa rulezi (probabil) o singura data. De ce ai mai multe frame-uri de input/logica per frame de render?

"Am crezut ca esti ceva mai avansat" - Nekitu, 2008 A.D.
Autobaza


Status:
Înregistrat pe:
12 May 2007 20:12:30
Vârsta: ? ani
Mesaje: 740
Locatie:
Programator

 
    Postat la 06 Feb 2009 19:31:46    Subiect: Re:
Deliverance info:

Deliverance:

Dark a scris:


De ce faci chestia aia cu acumulatorul acolo?


Chestia asta o fac din dorinta de a face update la diversele animatii de pe ecran cu time increments de aceeasi valoare. Astfel indiferent de numarul de frameuri pe care le am si de timpul care trece de la un frame la altul voi face update tot timpul cu acelasi time increment. Am facut chestia asta pentru ca framerateul varia uneori si bila de pe ecran sarea dintr-o pozitie in alta; citind articoul asta: http://gafferongames.com/game-physics/fix-your-timestep/ si implementand metoda am ajuns la concluzia ca metoda e destul de buna pentru a elimina miscarile bruste ale bilei.


Cind ai vsync, pentru fiecare frame pictat o sa rulezi input-ul de 3 sau 4 ori, iar cind n-ai, o sa rulezi (probabil) o singura data. De ce ai mai multe frame-uri de input/logica per frame de render?


Da, ai dreptate, nu e o idee prea buna ce fac eu acolo; am mutat input sa se execute once per frame insa problema cu input delay tot apare la 60 fps. Chiar daca fac un update per frame, fara sa folosesc acumulatorul tot se misca cu delay pad-ul. Solutia pe care am gasit-o pana acum este sa am update la intervale mai mici de 1 / 60 -> like 0.005 secunde. Ma intreb ce fac aiurea Very Happy

Ultima editare efectuată de Deliverance pe 07 Feb 2009 02:13:50; 2 editări în total


Status:
Înregistrat pe:
13 Oct 2006 10:05:37
Vârsta: 25 ani
Mesaje: 253
Locatie: Iasi , Romania
Programator

 
    Postat la 06 Feb 2009 20:27:12    Subiect: < fara subiect >
Dark info:

Dark:

Eu m-am gindit ca articolul ala e inspiratia buclei, da' ai zis ca faci o clona de breakout, pentru care e overkill. "Fizica" de care ai nevoie in breakout n-are de ce sa explodeze cind ai fps intre 30 si 1000.

Daca ai putea sa postezi tot codul, ar fi mai usor sa-si dea cineva seama ce se intimpla de ai lag.

"Am crezut ca esti ceva mai avansat" - Nekitu, 2008 A.D.
Autobaza


Status:
Înregistrat pe:
12 May 2007 20:12:30
Vârsta: ? ani
Mesaje: 740
Locatie:
Programator

 
    Postat la 06 Feb 2009 21:16:55    Subiect: Re:
Deliverance info:

Deliverance:

Dark a scris:

Eu m-am gindit ca articolul ala e inspiratia buclei, da' ai zis ca faci o clona de breakout, pentru care e overkill. "Fizica" de care ai nevoie in breakout n-are de ce sa explodeze cind ai fps intre 30 si 1000.

Daca ai putea sa postezi tot codul, ar fi mai usor sa-si dea cineva seama ce se intimpla de ai lag.


Well, din nefericire tot codul is a little monster ( > 600kb ) asa ca nu prea pot sa-l postez. Acuma ma gandesc ca nu e nevoie de tot codul ci doar de anumite parti ale lui. Asa ca am facut un mic demo care sa ilustreze problema. Updateul il fac in joculetz asa cum il fac in codul de mai jos.

EDIT: mouse move pentru a misca "padul" si space pentru VSync on si off.
Se observa ca avand VSync *ON padul se misca cu un mic delay.
Also vad ca imi mananca includeurile asa ca am pus apostrof in loc de .

Cod sursă:

#include 'stdlib.h'    // For malloc() etc.
#include 'stdio.h'     // For printf(), fopen() etc.
#include 'math.h'      // For sin(), cos() etc.
#include 'GL/glfw.h'   // For GLFW, OpenGL and GLU

#pragma comment (lib, "glfw.lib")
#pragma comment (lib, "opengl32.lib")
#pragma comment (lib, "glu32.lib")

float theFov = 45.0f;
#define RADIANS 0.017453292519943295769236907684886
bool VSync = true;

int theFPS = 0;
int currentFPS = 0;

void SetVSync()
{
    VSync = !VSync;

    glfwSwapInterval(VSync);
}

float UnProjectX(int xValue, float zNear)
{        
    float h = 2.0f*zNear*tan(theFov / 2 * RADIANS);
    float w = 1.33333333f*h;
    return float(xValue)/ 800.0f*  w - w / 2;
}

void clamp(float & value, float min, float max)
{
    if (value  max)
        value = max;
}

void DrawQuad(float x, float y, float w, float h)
{
    glBegin(GL_QUADS);
        glVertex2f(x - w/2, y - h/2);
        glVertex2f(x + w/2, y - h/2);
        glVertex2f(x + w/2, y + h/2);
        glVertex2f(x - w/2, y + h/2);
    glEnd();
}

float padPos[2] = {0.0f, -2.0f};
void UpdatePad(float amount)
{
    int x,y;
    int middleX = 400;
    glfwGetMousePos(&x, &y);

    int pixelsMoved = x - middleX;
    float oglUnitsMoved = UnProjectX(pixelsMoved, 6.0f) -
                          UnProjectX(0.0f, 6.0f);
    
    padPos[0] += oglUnitsMoved;
            
    clamp(padPos[0], -2.7f, 2.7f);

    glfwSetMousePos(middleX, y);
}

void Update()
{
    float amount = 1.0f / 500.0f;    
    static float accumulator = 0.0f;
    float currentTime = glfwGetTime();
    static float lastTime = currentTime;
    accumulator += currentTime - lastTime;
    lastTime = currentTime;
        
    glfwPollEvents();        

    while (accumulator >= amount)
    {
        UpdatePad(amount);    
    
        accumulator -= amount;
    }
}

void Draw( void )
{
    glClear( GL_COLOR_BUFFER_BIT );
    glLoadIdentity();
    glTranslatef(0.0f, 0.0f, -6.0f);

    DrawQuad(padPos[0], padPos[1], 1.0f, 0.2f);
    
    glfwSwapBuffers();
}


//----------------------------------------------------------------------
// main() - Program entry point
//----------------------------------------------------------------------

void GLFWCALL My_Key_Callback(int key, int action)
{
  if (key == GLFW_KEY_SPACE && action == GLFW_PRESS)
    SetVSync();
}
 
int main( int argc, char **argv )
{
    int    ok;             // Flag telling if the window was opened
    int    running;        // Flag telling if the program is running

    // Initialize GLFW
    glfwInit();

    // Open window
    ok = glfwOpenWindow(
        800, 600,          // Width and height of window
        8, 8, 8,           // Number of red, green, and blue bits for color buffer
        8,                 // Number of bits for alpha buffer
        24,                // Number of bits for depth buffer (Z-buffer)
        0,                 // Number of bits for stencil buffer
        GLFW_WINDOW        // We want a desktop window (could be GLFW_FULLSCREEN)
    );

    // If we could not open a window, exit now
    if( !ok )
    {
        glfwTerminate();
        return 0;
    }

    // Set window title
    glfwSetWindowTitle( "My OpenGL program" );

    // Enable sticky keys
    glfwEnable( GLFW_STICKY_KEYS );

    // Main rendering loop

    // Set up projection matrix
    glMatrixMode( GL_PROJECTION );    // Select projection matrix
    glLoadIdentity();                 // Start with an identity matrix
    gluPerspective(                   // Set perspective view
        theFov,                         // Field of view = 65 degrees
        (double)800/(double)600, // Window aspect (assumes square pixels)
        1.0,                          // Near Z clipping plane
        100.0                         // Far Z clippling plane
    );
    
    glMatrixMode(GL_MODELVIEW);

    // Set viewport
    glViewport( 0, 0, 800, 600 );
    
    glfwDisable ( GLFW_MOUSE_CURSOR );    

    glfwSetKeyCallback(My_Key_Callback);

    SetVSync();

    do
    {    
        Update();
        
        Draw();                
        
        currentFPS++;
        
        float currentTime = glfwGetTime();
        static float lastTime = 0; // update din prima
        
        if (currentTime - lastTime >= 1.0f)
        {
            lastTime = currentTime;
            theFPS = currentFPS;
            currentFPS = 0;
            
            char mess[256];
            sprintf(mess,"%s FPS: %d", VSync ? "VSync enabled" : "VSync disabled",
                        theFPS);
            glfwSetWindowTitle(mess);
        }

        // Check if the escape key was pressed, or if the window was closed
        running = !glfwGetKey( GLFW_KEY_ESC ) &&
                  glfwGetWindowParam( GLFW_OPENED );
    }
    while( running );

    // Terminate GLFW
    glfwTerminate();

    // Exit program
    return 0;
}

 

Ultima editare efectuată de Deliverance pe 06 Feb 2009 21:20:35; 4 editări în total


Status:
Înregistrat pe:
13 Oct 2006 10:05:37
Vârsta: 25 ani
Mesaje: 253
Locatie: Iasi , Romania
Programator

 
    Postat la 07 Feb 2009 20:10:32    Subiect: < fara subiect >
Dark info:

Dark:

Hmm... e destul de dubios, si sint mai multi factori aici.

In primul rind, intr-o poza cu contrast asa de mare (pad alb pe background negru), probabil poti vedea mai mult de 60 de fps, deci ceea ce percepi ca lag chiar e lag. E o chestie subiectiva, dar ia incearca sa faci pad-ul gri cu glColor3f(0.5f, 0.5f, 0.5f) si background-ul gri cu glClearColor(0.8f, 0.8f, 0.8f, 1.0f) si s-ar putea sa se reduca din efect. Sistemul vizual uman e destul de pretentios la chestiile astea si detaliile mici fac diferenta.

Alta chestie ar fi pointer ballistics. Nu-s sigur ca daca samplezi la 4000 de Hz obtii exact aceeasi miscare ca la 60 de Hz. De altfel nici nu stiu ce face GLFW ala cind chemi glfwPollEvents(), daca foloseste WM_MOUSEMOVE sau face GetCursorPos() de fiecare data.

Ar putea conta si cind faci SwapBuffers(). Tu desenezi frame-ul curent si faci imediat SwapBuffers(). Poti paraleliza un pic daca faci Draw(), Update() si abia la sfirsit Swap(), ca in felul asta GPU-ul merge in acelasi timp cu input-ul si update-ul. In cazul de fata, cind Update() nu face nimic interesant si GPU-ul freaca menta, nu conteaza, ba chiar introduce un frame de lag, dar in alte cazuri e important.

Am pus aici niste cod care face ce faci si tu, dar proceseaza mouse-ul cu raw input, ca sa nu fie faultat de pointer ballistics si comasari dubioase de WM_MOUSEMOVE. Vezi daca ti se pare ca are mai putin lag, mie mi-e greu sa zic. Smile La fel ca si la tine, space controleaza vsync-ul, dar mai doua controale. Cu 'c' poti pune FPS cap la 60 cu Sleep(), ca sa vezi daca-i o diferenta intre lag-ul introdus de vsync si lag-ul introdus de Sleep(). Cu 'f' controlezi daca SwapBuffers() se face imediat dupa desenare, sau intre input si desenare, ca in paragraful anterior.

Daca ti se pare ca miscarea e mai proasta decit in exemplul tau, chiar si fara vsync, e din cauza ca esti obisnuit sa ai pointer ballistics, pe cind raw input iti da miscare liniara. Partea buna e ca, odata ce esti multumit cu lag-ul, poti implementa singur acceleratie pentru mouse la tine in cod, si stii ca detii controlul, nu ca atunci cind face windows-ul diverse chestii cu WM_MOUSEMOVE.

"Am crezut ca esti ceva mai avansat" - Nekitu, 2008 A.D.
Autobaza


Status:
Înregistrat pe:
12 May 2007 20:12:30
Vârsta: ? ani
Mesaje: 740
Locatie:
Programator

 
    Postat la 07 Feb 2009 21:01:23    Subiect: < fara subiect >
Deliverance info:

Deliverance:

Am testat! Miscarea cand este pus cap la 60 are lag, chiar mai mare ca atunci cand se foloseste VSync si nu Sleep pentru cap. Cand VSync este off se misca bine. M-am uitat de curiozitate sa vad ce face glfw la PollEvents; printre altele cheama PeekMessage & DispatchMessage asa se ajunge la WM_MOUSE_MOVE unde sunt actualizate 2 variabile ce contin pozitia mouse-ului:

Cod sursă:

    // Check for new window messages
    while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
    {
        switch( msg.message )
        {
            // QUIT-message (from close window)?
            case WM_QUIT:
                winclosed = GL_TRUE;
                break;

            // Ok, send it to the window message handler
            default:
                DispatchMessage( &msg );
                break;
        }
    }
 


Smecheria cu swap last nu m-a ajutat dar se poate dovedi utila in cazuri in care am un update mai cpu intensive. De fapt cred ca ideal ar fi ca Render si Update sa se execute in timpi aproximativi egali si astfel chem Render -> transmite informatii spre GPU(el incepe lucrul) apoi chem Update(), cat timp GPU e busy se executa update si la sfarsit fac swapBuffers(rapid). Cred insa ca in practica lucrurile nu sunt asa simple.

Am reusit sa rezolv problema de lag(pe configuratii de pc-uri tinta) optimizand operatiile din functia Render(batching & minimize render states). Sigur pe calculatoare in care fps-ul va fi mai mic tot va fi vizibil un lag. Iar in legatura cu implementarea unei acceleratii a pad-ului.. poate fi interesanta dar ma gandesc ca ar ridica o dificultate de gameplay chiar daca nu foarte mare.


Status:
Înregistrat pe:
13 Oct 2006 10:05:37
Vârsta: 25 ani
Mesaje: 253
Locatie: Iasi , Romania
Programator

 
    Postat la 08 Feb 2009 12:29:27    Subiect: Re:
Dark info:

Dark:

Deliverance a scris:


Am reusit sa rezolv problema de lag(pe configuratii de pc-uri tinta) optimizand operatiile din functia Render(batching & minimize render states).


Pai stai ca n-am inteles... jocul tau avea oricum mii de FPS fara VSync, nu? Ce au rezolvat optimizarile alea, ca atunci cind pui VSync on ai 60 de FPS cu sau fara optimizari, nu?

Deliverance a scris:


Iar in legatura cu implementarea unei acceleratii a pad-ului.. poate fi interesanta dar ma gandesc ca ar ridica o dificultate de gameplay chiar daca nu foarte mare.


Daca nu folosesti raw input, ai deja acceleratie la miscarea mouse-ului, nu trebuie sa mai faci si tu. Nu creste dificultatea, dimpotriva. Si cursorul din Windows (sau orice alt OS) are acceleratie, altfel ar fi groaznic de folosit. Vezi aici detalii. Doar cind folosesti raw input trebuie sa-ti pui problema sa implementezi singur acceleratia, pentru ca raw input iti da exact ce vine de pe bus, de la mouse, fara procesare.

"Am crezut ca esti ceva mai avansat" - Nekitu, 2008 A.D.
Autobaza


Status:
Înregistrat pe:
12 May 2007 20:12:30
Vârsta: ? ani
Mesaje: 740
Locatie:
Programator

 
    Postat la 08 Feb 2009 15:09:02    Subiect: Re: Re:
Deliverance info:

Deliverance:

Dark a scris:

Deliverance a scris:


Am reusit sa rezolv problema de lag(pe configuratii de pc-uri tinta) optimizand operatiile din functia Render(batching & minimize render states).


Pai stai ca n-am inteles... jocul tau avea oricum mii de FPS fara VSync, nu? Ce au rezolvat optimizarile alea, ca atunci cind pui VSync on ai 60 de FPS cu sau fara optimizari, nu?


Well avea mii de fps pe calculatorul meu dar nu si pe unul cu placa video integrata Very Happy


Status:
Înregistrat pe:
13 Oct 2006 10:05:37
Vârsta: 25 ani
Mesaje: 253
Locatie: Iasi , Romania
Programator

 

Pagina 1 din 2 [ 1 | 2 ]


Server time: 08:56:26 19.05.2012



[ Termeni si conditii | Contact | F.A.Q. | Funny Pictures ]

© 2006 - 2012 Copyright 7thFACTOR Entertainment - All rights reserved