Results 1 to 17 of 17

Thread: GetVerticalBlankStatus/WaitForVerticalBlank

  1. #1

    Thread Starter
    The Idiot
    Join Date
    Dec 2014
    Posts
    2,721

    GetVerticalBlankStatus/WaitForVerticalBlank

    Im interested in this particular function, that you can find in directx. Looking around you can find a lot of examples, even with vb6.
    mostly they want you to install some drivers, but I hate that, just for one function I need to make an installer?
    its quite simple really:

    - DirectDrawCreate
    - GetVerticalBlankStatus (if true or false)

    or

    - DirectDrawCreate
    - WaitForVerticalBlank (that will act like a timer)

    I checked Mikle, DX9 project, but I can't find this function. I think Cairo also uses it, but I don't want to install that just for one thing, I like my programs to be dll/ocx-free.
    is there a way to use those functions without the need to register a dll?
    and if I need any of those dx#vb.dll, can I call that specific API without referring it or installing the .dll for it?

  2. #2
    Fanatic Member Spooman's Avatar
    Join Date
    Mar 2017
    Posts
    868

    Re: GetVerticalBlankStatus/WaitForVerticalBlank

    baka

    I'm afraid I haven't heard of them before, so, could you describe what they should do

    Spoo

  3. #3

    Thread Starter
    The Idiot
    Join Date
    Dec 2014
    Posts
    2,721

    Re: GetVerticalBlankStatus/WaitForVerticalBlank

    they tell you when the monitor is "drawing", knowing this, you can adjust your rendering to avoid tearing.
    theres no windows API to get it, and its quite odd that windows don't have a way to know. even windows sometimes misses vsync.
    directx have it.

    right now I just render as much possible, even if its most of the frames are just pointless.
    when I make lots of movements I need to increase fps to avoid flickering, but with a way to know the refresh rate I could keep the same fps all the time.

    having a way to know, I can lower fps and increase screen size and quality.
    its not that gdi is bad. I can reah 250-500 fps (800x600), so its good enough. but no API to check the refresh rate its annoying.

    so what I need is to know the exact moment when the monitor is rendering.
    I can "get" the scanline, so I know the refresh rate of the monitor, but theres no API to get "when" it happens.

  4. #4
    PowerPoster Arnoutdv's Avatar
    Join Date
    Oct 2013
    Posts
    5,854

    Re: GetVerticalBlankStatus/WaitForVerticalBlank


  5. #5
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: GetVerticalBlankStatus/WaitForVerticalBlank

    Hi baka. I'm going to copy+paste my reply to a similar thread on this topic:

    DwmGetCompositionTimingInfo has everything you need to do this yourself, but note that there is little point if you are using standard drawing methods (e.g. rendering to a window). The DWM in Vista+ handles composition and vsync automatically.

    You only need to worry about tearing if you are rendering directly to the "screen", which usually means you are already using DirectX or OpenGL instead of GDI/System.Drawing/etc.

    (Note also that modern monitors can have variable refresh rates a la FreeSync or G-Sync, which would make this approach even more complicated.)
    If you are experiencing tearing, there are much easier solutions that attempting to manually sync with screen updates (especially because refresh rates can now vary dynamically). Can you explain a little more about how your rendering works? Are you rendering directly to a picture box or form, or are you rendering to an in-memory DC (or something else)?
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  6. #6

    Thread Starter
    The Idiot
    Join Date
    Dec 2014
    Posts
    2,721

    Re: GetVerticalBlankStatus/WaitForVerticalBlank

    EnumDisplaySettings doesn't work.
    tried with different settings and also googled it. maybe doesn't work for windows 7 64bit?

    looking around, I found a gdi32 API: GetDeviceCaps
    theres a parameter VREFRESH, that would give the same as EnumDisplaySettings, but even that one I can't make it to work.

    I think I remember using one API to get the scanlines, but I have forgot how.
    but, even knowing the scanlines how can that help me?

    Tanner_H, I was actually looking into DwmGetCompositionTimingInfo, but I don't know how to make it work, it result in a negative long.
    Im rendering in a picturebox using StretchBlt, everything set to false and the pre-work is done in a memory DC.
    im not getting any errors or tearing/stuttering. I just want a way to know when the monitor is about to refresh (not the same as vb6 own paint refresh)
    Last edited by baka; Oct 16th, 2017 at 11:09 AM.

  7. #7
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: GetVerticalBlankStatus/WaitForVerticalBlank

    Good work rendering to a memory DC! That is a good way to approach this.

    EnumDisplaySettings does work, but it is a bit cumbersome to use it. This article details the basic steps you need to take:

    Win32: How to get the refresh rate for a window

    Generally speaking, because Windows handles vsync for you, it may make more sense to simply pick the refresh rate *you* want for your program. If you want 60 fps, for example, you can set your program loop to do all its rendering, then simply sleep/wait until 16.67 ms have passed. Then StretchBlt from your memory DC to the target picture box, and repeat. 60 fps is the standard refresh rate for most UI tasks, so it is a good place to start.

    (This is an especially good approach on laptops, so you don't burn through battery power rendering "pointless frames", as you say.)
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  8. #8

    Thread Starter
    The Idiot
    Join Date
    Dec 2014
    Posts
    2,721

    Re: GetVerticalBlankStatus/WaitForVerticalBlank

    thats the problem. I have tried to do that before,
    if I lower the fps to 60, it run ok, but when I move around, its not smooth. this because it takes more time to "render"
    if I instead let the program run the fps dynamically, the movement gets smoother.
    my game have lots of movement and animations going on, its a full 800x600 with multiple layers.
    it takes around 2-5ms to render everything in the memoryDC. so its not much, if I have 16ms its enough time. but I need to know exactly when the monitor refresh,
    doing so I will start the rendering process after the monitor refresh it started, and then I have 16.67ms (or whatever rate the monitor have) to do everything and render to the picturebox before the next refresh.

    the only thing I get from that site is the refresh rate, not when the monitor actually refreshes.
    this is what people are discussing around the net, that directx have this approach and thats why it run smooth while in windows we dont have it.

    im not sure windows refresh for me. it refresh when I send something to refresh.
    are there any accurate sleep functions? sleep is not accurate enough to make those 16.67ms or whatever I have left after the rendering.
    if Im just using a timer (looping + doevents), I get 16ms, not 16.67ms. running at 16 or 17ms creates tearing as well.

  9. #9
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: GetVerticalBlankStatus/WaitForVerticalBlank

    If I can be blunt, baka: I don't know why you think this problem is tied to a monitor's refresh rate. It isn't.

    Syncing with the actual display hardware is handled 100% by the DWM built into Windows. As a VB6 developer, you have no control over when your updates are actually posted to the screen. Windows takes care of all this in the background, because it has to composite all the other windows and elements on your display before posting pixel data to the screen.

    Even if you know when a display is going to "refresh", it won't help, because Windows decides when to composite your picture box to the screen. Even if you request a refresh at the precise moment before the screen refreshes, Windows will get to your request whenever it wants to, while taking many other considerations into play. Microsoft explains this in more detail here:

    The desktop composition feature, introduced in Windows Vista, fundamentally changed the way applications display pixels on the screen. When desktop composition is enabled, individual windows no longer draw directly to the screen or primary display device as they did in previous versions of Windows. Instead, their drawing is redirected to off-screen surfaces in video memory, which are then rendered into a desktop image and presented on the display.
    If you lower the fps and your program is not smooth, that indicates some other problem. It might have to do with how your animations are calculated. I can only guess without source code.

    Generally, the way you want to calculate animations is to determine them based on how much time has passed since the last render (because you can't guarantee this will always be 16.67 ms anyway, especially in a multitasking world). When your game loop processes, calculate how many ms have elapsed since the last time your loop was called (maybe 0.016 seconds in a "perfect" world). Use that elapsed time to figure out how much your animation should move, then paint it to its new position. This way, whether your game runs at 30 fps or 240 fps, your animations will always be painted correctly.

    This approach is much better than something like "move X pixels every time the game loop processes", because the game loop will never occur with very precise timing. This is true even on dedicated hardware like game consoles.

    Anyway, for more precise timing results, you can always use API time measurements instead of built-in Windows ones. But without source code, this is all just guesses.

    Just know that desktop applications can run just fine without ever knowing detailed display refresh data. This is why Microsoft doesn't make it easy to get that data. As they explain at the MSDN link above, there are only very limited scenarios where you need real-time compositing data (applications like Skype that must synchronizing streaming behavior across a network, for example).
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  10. #10

    Thread Starter
    The Idiot
    Join Date
    Dec 2014
    Posts
    2,721

    Re: GetVerticalBlankStatus/WaitForVerticalBlank

    but why do we have this with directx and resulting in a more smooth animation? just google around and you will see a lot of people discussing this.

    yeah, right now im doing exactly that. the fps is calculated dynamically. sometimes 60 sometimes 300, depending whats going on. each second readjust the speed and fps.
    moving, I know for sure it will require more fps, so I put the sleep to 1 and let it go, of course the fps goes up to a maximum and the animation is readjusted automatically.
    so theres no problem that my animations goes wild or superslow, everything is ok.

    the problem is that im forced to let the fps peak up while moving, of course, once stopped, it will go back to a normal fps.
    if Im not doing that, I get from time to time stuttering. but not always, its like the refresh rate can't follow everything thats going on or that its follow a hz thats not synchronous with the rendering.

    we discussed this that allowing that high fps only consume cpu, but now, with your response its like thats the solution for me.
    well, its not that its doesn't work. but I wanted to see if there was a way to lower fps and keep the smoothness.

    maybe I need to change the mechanism and use that subclassing method, paint event etc. not sure. but i did try that a while ago and that didn't help.

  11. #11
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: GetVerticalBlankStatus/WaitForVerticalBlank

    Quote Originally Posted by baka View Post
    but why do we have this with directx and resulting in a more smooth animation? just google around and you will see a lot of people discussing this.
    Because DirectX is a totally different way of doing things. With DirectX, you are not drawing to VB picture boxes. You are rendering to DirectX surfaces which obey totally different rules. DirectX can bypass the DWM completely, which allows it to do things you cannot do otherwise.

    Using DirectX strategies on GDI and VB code makes no sense.

    the problem is that im forced to let the fps peak up while moving, of course, once stopped, it will go back to a normal fps.
    if Im not doing that, I get from time to time stuttering.
    Is there some way you can provide sample code? Otherwise, we'll just be making wild guesses at how to help.
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  12. #12

    Thread Starter
    The Idiot
    Join Date
    Dec 2014
    Posts
    2,721

    Re: GetVerticalBlankStatus/WaitForVerticalBlank

    form: 1 picturebox, autoredraw=false, hasDC=false

    the "core" is this, the "loop"
    sys.s is the "speed" variable that is used in the "memory" rendering.
    Code:
        timeBeginPeriod 1
        Do
            If sys.timer = 2 Then lt = timeGetTime
            t = timeGetTime
            dt = (t - lt): If dt > 0 Then sys.s = dt / 8
            lt = t
            t = t / 1000
            If t > cSec Then cSec = t: tmrFPS
            sys.timer = 0
            '
            Render
            '
            FPS = FPS + 1
            DoEvents
        Loop Until ExitCode
    tmrFPS will update the FPS sleep, the sys.timer is used to bypass it if needed
    Code:
    Sub tmrFPS()
        If sys.timer < 2 Then
           ' default 150/75
            If FPS > 100 Then sys.R = sys.R + 1
            If FPS < 60 And sys.R > 1 Then sys.R = sys.R - 1
            FPS = 0
        End If
    End Sub
    render is the function that do the "work"
    img.cls will "clear" the dcmemory, could be with a background color or an image.
    after that we have a number of different classes, I only include map.Render (everything is rendered in memoryDC)
    the sys.timer is triggered if we sleep or not.
    img.renderDC will put the finished memoryDC directly into the picturebox using StretchBlt. nothing more happens there.
    Code:
    Sub Render()
        Img.Cls
        map.Render 
        DoEvents
        Select Case sys.timer
            Case 0: Sleep sys.R
            Case 1: Sleep 1: sys.R = 1
        End Select
        Img.RenderDC
        DoEvents
    End Sub
    I have tried to move img.renderDC before or after the sleep, but same result.
    I have tried to use a fixed timer to call render instead of using sys.timer/sleep. but that didnt give me any better results.
    using a fixed interval, set to 70-80 fps. using the timeGetTime to know "when" to call the render, also, no better result.
    i have tried to put img.cls/map.render inside the "timeGetTime, to allocated amount of time to render it, and trigger
    img.renderDC exactly the same time (as map.render takes 3-5ms I can wait to 16ms to always call img.renderdc) but no better result.

  13. #13
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: GetVerticalBlankStatus/WaitForVerticalBlank

    Thanks for providing some sample code. Let's try some small ideas first.

    First: is it necessary to use so many DoEvents calls? If you need to yield for input messages, it's typically best to do it just once, rather than having DoEvents spread all throughout your code. DoEvents can cause large and unpredictable performance drops, so I would remove all DoEvents except just one if you can (we'll come back to this in a moment).

    Next. timeBeginPeriod 1 is not the best way to check time. If you look on MSDN:

    This function affects a global Windows setting. Windows uses the lowest value (that is, highest resolution) requested by any process. Setting a higher resolution can improve the accuracy of time-out intervals in wait functions. However, it can also reduce overall system performance, because the thread scheduler switches tasks more often. High resolutions can also prevent the CPU power management system from entering power-saving modes. Setting a higher resolution does not improve the accuracy of the high-resolution performance counter.
    So when that function is called, the entire OS is forced to use the resolution you request. Instead, let's use QueryPerformanceCounter. There is a really nice example of it at this vbforums link:

    http://www.vbforums.com/showthread.p...or-games-etc-)

    If it's not too tricky, you might try using that sample project to implement your game loop, and seeing what happens. It has FPS control built-in, and it uses a modified API replacement for DoEvents that will likely yield better results.
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  14. #14

    Thread Starter
    The Idiot
    Join Date
    Dec 2014
    Posts
    2,721

    Re: GetVerticalBlankStatus/WaitForVerticalBlank

    added QueryPerformance, run some tests.

    using the function to make a "fixed" framerate didn't help. moving around the map (its a +1000/+1000 image while the view area is 800x600)
    creates stuttering. the only way is to increase fps to "lower/remove" the stuttering.

    changed the function so that I "clone" my old loop method with timeGetTime but using QueryPerformance.
    running with the old method using timeGetTime, I reach 180fps, while in QueryPerformance I get 150fps (from a laptop)
    150fps is not bad, but the stuttering is still there, running at 180fps show less.

    using GetQueueStatus as well, but its not that I can see any difference. if theres a increase of performance its not something I can judge by looking.

    conclusion-
    it seems that timeGetTime affect the performance of the game, adding 30 extra fps.
    the movement is smoother and less stuttering if I use timeGetTime.
    I like using QueryPerformance, if the timeGetTime can affect negatively the system, but is -30fps worth it? (on a laptop, could be a lot more on a desktop computer, I can try tomorrow when I get home)
    to run with a fixed fps didnt add any smoothness at all. I tried with a fixed 60fps and 90fps. with 90fps I gained a bit more smoothness, but still more stuttering then using a "dynamic" fps.
    I learned about GetQueueStatus and I think I will use that from now on. if DoEvents can cause performance drops. in my case im not sure DoEvents can create problems, this because Im not using other components, just 1 picturebox. maybe If we have lots of components, vb6 own timer, usercontrols etc, then I believe the GetQueueStatus could increase performance!

  15. #15

    Thread Starter
    The Idiot
    Join Date
    Dec 2014
    Posts
    2,721

    Re: GetVerticalBlankStatus/WaitForVerticalBlank

    I tried the suggestion from LaVolpe to use 1 dc and it messed up everything.
    it seems that half of the images worked. not sure if it have anything to do with the format, as some images have alpha some not. it also crashed a few times. so im back to square one.

    now, using timeGetTime and only 1 DoEvents with GetQueueStatus this time.

  16. #16
    Fanatic Member Spooman's Avatar
    Join Date
    Mar 2017
    Posts
    868

    Re: GetVerticalBlankStatus/WaitForVerticalBlank

    Baka

    From your post #2
    right now I just render as much possible, even if its most of the frames are just pointless.

    when I make lots of movements I need to increase fps to avoid flickering, but with a way to know the refresh rate I could keep the same fps all the time.
    What does pointless mean?
    1. meaningless
    2. empty .. ie, have no drawing, no points, no lines
    3. other


    How are the movements invoked?
    1. by mouse drag
    2. by code
    3. other


    It might also help if you could post a screenshot

    Spoo

  17. #17

    Thread Starter
    The Idiot
    Join Date
    Dec 2014
    Posts
    2,721

    Re: GetVerticalBlankStatus/WaitForVerticalBlank

    pointless, means that I render a lot, up to 300-400 fps. i mean, we can play very heavy games with lots of moments at 60fps without flickering.

    movements are invoked by key, using KeyDown and KeyUP. I have 4 booleans for each arrow key that tells if its pressed or not.
    inside the loop if key is true it add/sub x/y using the delta/speed (so that its synchronous with the fps).
    the x/y is the viewing area left/top, that is processed in the memoryDC. only the viewing area is rendered. lastly using StretchBlt to render it to the picturebox.
    each area have different dimensions, example 3100x1100, but the viewing area is 800x600. the x/y moves around that area.
    all the area have activity, but only the viewing area gets rendered, outside the region is "cutted out", so that we dont do unneeded rendering.
    im not moving the picturebox at all. its fixed.

    the flickering is the same effect we have when working in vb6 (when the windows visual changes to basic) and we do lots of movements.
    if I run the project in IDE, it flickers even more, even with the "free-fps" mode. so I need to compile the project and run it with VB6 closed to get best result.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width