Thread: events, frame rates, and the pipeline

  1. #1
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300

    events, frame rates, and the pipeline

    Okay, I don't play video games, so I have a crap video card -- actually I don't have a video card at all, I use the onboard via chrome from my mobo. But I really want to write a video game (a 3D FPS version of breakout) as a winter project.

    I've always been slightly puzzled by gamers obsession with frame rates. Like film is I think <30 fps, so why bother with more? Yes that's a genuine question, cause I presume there is a genuine reason, I'm not calling anyone a fool.

    This afternoon I was wondering if it relates to events, and "the pipeline". Lemme describe my programming issue to explain why I'm thinking that.

    For a 3D FPS breakout, you are the paddle, so the paddle moves in x and y but not z, which makes the mouse perfect. But today I was experimenting with openGL in both SDL and glut and I noticed something: the data I got from mouse events was instantaneous -- I used it to modify global variables and printf them, those changes appear instantaneously -- but the response in the graphics display noticeably lags, I would say at least 1/2 second. This does not make sense to me, since I am getting 25-45 fps*. I presumed that there is no temporal offset, but that is not necessarily so -- that is, you could get 100 fps, but at a 1 second delay. It is a "pipeline", so I suppose there must be some delay from the time data is fed into one end (when the "render frame/scene" function is called) to when the graphics lib, etc, have done their job and the frame actually appears on the scene, because it is obvious from the console debugging data (printf) that the frame currently executing is at least 10-15 frames ahead of what appears in the application window.

    Is that right? Is that normal? Is that a consequence of a crappy video card and software acceleration? Or am I out to lunch here? Suddenly, it might make sense to want 60 fps, if the delay is a number of frames, and especially if that number was also reduced. If the offset were 5 frames at 60 fps, that's 1/12th of a second, more or less instant. But with what I am looking at right now the action is gonna be really lame.

    *presumably this will start to diminish when the graphics gets heavier, but by then I will probably be motivated to buy a card
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  2. #2
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    It's all about samples. There are more samples between time T and time T2 at 60 FPS than at 30 FPS. More samples will yield smoother presentation, more responsive devices, etc, etc.

    60 FPS is 1 frame per 16.66666667 ms or 1000 / 60.
    30 FPS is 1 frame per 33.33333333 ms or 1000 / 30.
    20 FPS is 1 frame per 50 ms or 1000 / 20.

    At 60 FPS the entire system is being updated every 16.666666667 ms. Most physics systems will be clamped here but nothing says the video has to be. If vsync is turned off...or if triple buffering is on and the triple buffer is unused at render time...you can achieve far more than 60 FPS.

    So 60 FPS is actually saying we have split 1 second into 60 separate time slices. Obviously the more distinct sample points you have between 0.0f and 1.0f the better. That is the whole thrust behind the FPS argument. It's not just the video running at this speed, it is the entire system or the entire game. If one aspect takes more time than usual every other system takes a hit - that is every system that is not in a thread.

    Imagine in online play you are running at 5 FPS and you are trying to shoot one of your buddies in a deathmatch. At 5 FPS it is going to be extremely hard, nigh impossible, to actually hit your friend. There are only 5 distinct samples of gameplay in 1 second which means it won't even be interactive enough to use. So if your friend is running from point A to point B and the journey takes 1 second, you only get 5 distinct time slices of his movement from A to B. If you are at 60 FPS you will get 60 distinct time slices or 60 unique 'snapshots' in time of his movement from A to B. You are 12 times as likely to hit him when he is moving from A to B at 60 FPS than at 5 FPS. Likewise your mouse will be sampled 12 times as much in 1 second at 60 FPS than at 5 FPS.
    Last edited by VirtualAce; 11-18-2009 at 10:24 PM.

  3. #3
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Bubba View Post
    It's all about samples. There are more samples between time T and time T2 at 60 FPS than at 30 FPS. More samples will yield smoother presentation, more responsive devices, etc, etc.
    I understand that. What's happening is there a delay of 15-20 frames from when the drawing routine runs to when the frame makes it onto the display. Consider this:

    Code:
            glColor4f(0.0f,0.0f,0.0f,1.0f);
            if (!(reps%500)) {
                    printf("NOW\n");
                    glColor4f(1.0f,0.0f,0.0f,1.0f);
            }
            printf("*"); fflush(stdout);
            reps++;
    This is in the routine that draws the frame. The next object to be drawn is black, but once every 500 frames it will flash red, and also during that frame "NOW" should appear on the console in the background.

    That does not happen. There is a very clear delay. Every frame an asterisk is printed. I sit with one finger on ctrl and one over the c key. As soon as I see the object flash red, I kill the process:

    NOW
    ****************************************^C


    In other words, at my current frame rate, there is a delay of almost a full second between when the code is executed and when the frame is actually rendered on screen.

    The issue may be that I need to use a timer. I just went back to look at the OGL stuff I did before and low and behold, there is no such problem there. But in those, I used a one millisecond timer. I read in another forum that this was a bad idea and that you will get a faster frame rate by just allowing the drawing rountine to repeat as often as possible, and since I now want a game, I figured should stick as close as possible to conventional wisdom. Hopefully putting the timer back in will solve the problem.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  4. #4
    Registered User
    Join Date
    Mar 2007
    Posts
    416
    Quote Originally Posted by MK27 View Post
    ... The next object to be drawn is black, but once every 500 frames it will flash red, and also during that frame "NOW" should appear on the console in the background.
    ...
    ...
    In other words, at my current frame rate, there is a delay of almost a full second between when the code is executed and when the frame is actually rendered on screen...
    Console windows are not known for being very faster for printing so there might be a delay between when it was sent to the buffer of the console window and when you see NOW. In fact, when I initialize my trees it takes longer to display the information than it does to initialize/change the data. Printing almost always takes longer than drawing a rendered frame.

    Also have to take in to account your fingers are not as fast as a computer

  5. #5
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    That does not happen. There is a very clear delay. Every frame an asterisk is printed. I sit with one finger on ctrl and one over the c key. As soon as I see the object flash red, I kill the process:
    Which means you are off by at least 250 ms since that is the average response time of a human to an event.

    Setting breakpoints and timing the delay would be a better approach. I'm not sure why you are using printf() at all in an OGL app since any console output or OutputDebugString() will slow the system down.

  6. #6
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by scwizzo View Post
    Printing almost always takes longer than drawing a rendered frame.
    Well, if you had read the post you would have noticed what I clearly state is that the console output very clearly occurs BEFORE the frame is rendered. Without question, there is a delay of almost a full second between when the code is executed and when the frame appears.

    The reason I did this to start with was to debug why the mouse movement was lagging. It is of the sort where if I move the pointer (which is part of X, not OGL), it responds instantly. However, the response in the OGL window is very much delayed -- it is still smooth, this is NOT a low framerate problem. For example, if I quickly move the mouse a few inches and let go, the response in the OGL window does not even begin until my hand is off the mouse. So, no matter what you do with it, the movement visibly continues after your hand leaves the mouse.

    Thus, I added printf lines to show the raw mouse data the app had received. But even tho that line was after the line applying the transformation, it VERY CLEARLY appears on the console before the graphical response does, which means the code is being executed at that point, then there is ~ 1 second delay, then it appears in the OGL window.

    As for human response time, I agree I would expect a bit of a lag, but not anything like that much. As I said, it is visually apparent, I just wrote that little bit of code to make the issue clear. If human response time were that poor, no one would bother playing video games, catching balls, etc. If the delay were so short as to be less than my response time, I wouldn't care.

    I also agree use of stdout will slow things down if you are just doing computation in the background, but in this setting it does not affect the frame rate AT ALL. The console output appears instantaneously, it is the graphical output which lags.

    Quote Originally Posted by Bubba View Post
    Setting breakpoints and timing the delay would be a better approach. I'm not sure why you are using printf() at all in an OGL app since any console output or OutputDebugString() will slow the system down.
    Obviously you have not understood at all what I am talking about. Initially I used breakpoints just to make sure everything was happening properly. But it is totally stupid to use this to find a delay -- the application MUST continue. It cannot be stopped and started by me. As as for console output slowing the system down, like I just said, that is not what happens for me here.

    And, incidentally, 1) the same hesitation is evident in the debugger anyway, 2) many debuggers do run in the console, and you are a fool if you believe the GUI version is somehow faster, etc, so this whole thought you had here is oxymoronic.

    Anyone else? I would say this may be simply because I don't have a GPU, my routine is at the beginning of the pipeline, and the software emulation runs as a threaded processes, permitting those routines to be executed in advance of the low level work done by the library and video module. However, as mentioned before, I have earlier stuff I've done where this delay does not happen -- I move the mouse, the scene move simultaneously. At this point, the only differences in the style of the code is that the old stuff has lighting and texture, whereas this does not yet. I'm totally flummoxed.
    Last edited by MK27; 11-21-2009 at 08:24 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  7. #7
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    As for human response time, I agree I would expect a bit of a lag, but not anything like that much. As I said, it is visually apparent, I just wrote that little bit of code to make the issue clear. If human response time were that poor, no one would bother playing video games, catching balls, etc. If the delay were so short as to be less than my response time, I wouldn't care.
    Google it. Average response time is indeed 250 ms or 1/4 of a second. Average meaning some might be faster and some slower.

    Obviously you have not understood at all what I am talking about. Initially I used breakpoints just to make sure everything was happening properly. But it is totally stupid to use this to find a delay -- the application MUST continue. It cannot be stopped and started by me. As as for console output slowing the system down, like I just said, that is not what happens for me here.

    And, incidentally, 1) the same hesitation is evident in the debugger anyway, 2) many debuggers do run in the console, and you are a fool if you believe the GUI version is somehow faster, etc, so this whole thought you had here is oxymoronic.
    Take it down a notch my friend. My post was not intended to ignite a firestorm nor was I implying that you don't understand what is happening. If you were offended by my post please accept my sincerest apology b/c that is not what I wanted to do. I'm honestly trying to help but I am having difficulty understanding what exactly is happening.

    Based on this fact:
    In other words, at my current frame rate, there is a delay of almost a full second between when the code is executed and when the frame is actually rendered on screen.
    Framerate questions
    If the code to render the frame executes 1 full second before it is shown on the screen this implies a serious framerate issue. I'm not sure why you say otherwise since framerate would definitely be affected here.

    IE:
    Code:
    ...
    while (m_gameRunning)
    {
       Engine->Update();
       Engine->Render();
    }
    ...
    If it takes 1 full second before the results of Render() are shown this means that the video card or something else in the system is busy. This also means that no other frames can render during this time. So your best case scenario here is that you have a 1 second delay after every Render() before you can render again. Based on this information I cannot see how you are getting anything more than 1 FPS. The only way you could be getting more than 1 FPS is if the delay was not caused by the GPU. If it was caused by the GPU this would mean it could not render any more frames until the previous one was completed. Another option is that the rendering is threaded - however - this still has the limitation that only one thread can use the GPU at one time. If the main process is occupying the GPU for 1 full second then it does not matter if there are 500 other threads...they cannot use the GPU.

    I cannot think of any case where a 1 second delay after every render call would not clamp you to 1 FPS.

    I recommend that you allow your main update/render loop to run as fast as possible with no delays. If you are vsynced I recommend you turn triple buffering on. If you are concerned about taking CPU cycles then thread things like sound and input. This will bring the overall usage down...but personally I would not worry about maxing out the CPU.

    Things to check (for Direct3D at least but they may apply to OGL)
    • In D3D there is a setting in the DirectX control panel for maximum validation. If this is turned on you will get extremely poor FPS. I do not know if OGL has a similar setting for it's device.
    • Invalid calls. Ensure that your rendering does not have a huge slew of invalid calls. Invalid calls may not crash the system but they will slow it down considerably. Invalid calls in D3D are caused by incorrect parameters in API calls, calls that are not supported by the device, and calls that are made at the wrong time in the pipeline (Trying to render outside of a BeginScene()/EndScene() block, etc)
      I do not know OGL but I'm sure this can happen in it as well. So while the APIs are different the concepts here should remain the same.
    • Driver incompatibility. It does not happen often but I have ran across situations where a certain render calls run extremely poor on certain hardware but has no problem on other hardware.
      I ran into both of these issues when doing cubemapping. On my new NVidia 260 GTX PCI-E clearing the off-screen render target every frame and/or at the wrong time slowed the render down considerably. However on my older NVidia 7800 AGP neither of those slowed it down. I had to change the render method to suit my newer card. Older drivers had no issues with this but the newer ones appear to. Another example is some cards require power of 2 textures while others don't - and not all of them crash if you don't obey it. Some will just run very poorly.
    • Software emulation - if you make calls that are unsupported by your card the driver normally tries to emulate the functionality in software. This is extremely slow.
    Last edited by VirtualAce; 11-21-2009 at 11:05 PM.

  8. #8
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Bubba View Post
    Take it down a notch my friend. My post was not intended to ignite a firestorm nor was I implying that you don't understand what is happening. I'm honestly trying to help but I am having difficulty understanding what exactly is happening.

    If the code to render the frame executes 1 full second before it is shown on the screen this implies a serious framerate issue. I'm not sure why you say otherwise since framerate would definitely be affected here.
    I apologize Bubba, for letting my frustration get the best of me, but I absolutely promise the frame rate did not seem comprimised -- it was about the same as the program that works properly (altho less consistant -- sometimes it would be higher), despite the fact that that one contains a much more intense scene. At this point, the only difference besides the scene content is that the working one has normals determined in it (and the working one is also threaded with gtk, but the gtk thread does not contain any GL commands).

    Anyway, someone at the openGL forum says that it is possible that "your GL implementation stores too many GL commands before actual rendering takes place". Why this would effect one piece of code with near identical methodology to another piece of code, I do not know.

    Using glFlush() did not work. However, adding glFinish()*-- a command of which I was unaware -- right before glutSwapBuffers() did the trick. 3D game programming here I come When I add the normals in for this, I will try taking that out: I'm guessing something in the GL implementation flushes output during normalization, but not otherwise. It could also be that a heavier scene slows everything down enough that it catches up to itself.

    And, low and behold, the frame rate went up to a smooth 85 (the scenery heavy one is less than half that, coincidentally matching the problem code; I presume at a certain point I will need to get a card for hardware acceleration).

    *which the manual for glFinish():
    glFinish does not return until the effects of all previously called GL commands are complete. Such effects include all changes to GL state, all changes to connection state, and all changes to the frame buffer contents.
    does imply that "previously called commands" may be left incomplete otherwise. Elsewhere I have read the commands are executed "in batches to improve performance" which I take it that those "batches" are not the batches in my code. So, what I thought was happening, was happening.
    Last edited by MK27; 11-22-2009 at 12:34 PM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  9. #9
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Well it's good to hear you solved it. I'm definitely not an OpenGL guy so the only gotchas I know are related to Direct3D and trust me it has just as many as OGL does. The only way you learn about them is by going through what you did with this one. Often the documentation does not warn you about these types of issues so it really comes down to figuring it out on your own which royally sucks.

Popular pages Recent additions subscribe to a feed