# Visual Basic > Visual Basic 6 and Earlier >  [RESOLVED] how can the execution speed of loop be the same for different systems(Used OpenGL)

## Black_Storm

I have a loop to draw in OpenGL as follows:



```
PrgRun=true
Do
	call a
Loop While PrgRun


sub a()
Do
        glClear clrColorBufferBit Or clrDepthBufferBit
        glLoadIdentity
        glBindTexture GL_TEXTURE_2D, Texture(1)
        glTranslatef 0#, 0#, zoomg
        glRotatef 180, 0, 1, 0
        


        glBegin bmQuads
        glTexCoord2f 1#, 1#
        glVertex3f -1#, 1#, 0#
        glTexCoord2f 0#, 1#
        glVertex3f 1#, 1#, 0#
        glTexCoord2f 0#, 0#
        glVertex3f 1#, -1#, 0#
        glTexCoord2f 1#, 0#
        glVertex3f -1#, -1#, 0#
        glEnd
        
        SwapBuffers (frm.hDC) 'Puffer tauschen (Double Buffering)
        DoEvents
        
        zoomg = zoomg - 0.08:   Sleep 10
        
        If zoomg <= -4 Then needexit = True
    Loop While needexit = False
end sub
```



on the  CPU dual core  win 8 64bit , the speed is good, but in another system like as cput intel core3 win 10 64bit the speed is very slow, and in my opinion, the problem is from the upper loop. Is it possible to balance the speed so that the speed is the same in all systems?

maybe need use timer vb replace with loop or api timer?

----------


## baka

u can do a search here about game-loop.
the Trick shared how to use directx sync and instead of doevents use peekmessage.
D3DKMTWaitForVerticalBlankEvent is one of the API used.

----------


## Black_Storm

about D3DKMTWaitForVerticalBlankEvent  your means this ?
https://www.vbforums.com/showthread....=1#post5467901


```
' //
' // VSync
' // Vista and later
' // By The trick
' //


Option Explicit


Private Type LUID
    LowPart         As Long
    HighPart        As Long
End Type


Private Type D3DKMT_OPENADAPTERFROMHDC
    hDC             As Long
    hAdapter        As Long
    AdapterLuid     As LUID
    VidPnSourceId   As Long
End Type


Private Type D3DKMT_WAITFORVERTICALBLANKEVENT
    hAdapter        As Long
    hDevice         As Long
    VidPnSourceId   As Long
End Type


Private Type D3DKMT_CLOSEADAPTER
    hAdapter        As Long
End Type


Private Declare Function D3DKMTOpenAdapterFromHdc Lib "gdi32" ( _
                         ByRef tAdapter As D3DKMT_OPENADAPTERFROMHDC) As Long
Private Declare Function D3DKMTWaitForVerticalBlankEvent Lib "gdi32" ( _
                         ByRef tEvt As D3DKMT_WAITFORVERTICALBLANKEVENT) As Long
Private Declare Function D3DKMTCloseAdapter Lib "gdi32" ( _
                         ByRef tAdapter As D3DKMT_CLOSEADAPTER) As Long


Private m_bIsRunning    As Boolean
Private m_lFPSCounter   As Long


Private Sub cmdStop_Click()
    m_bIsRunning = False
End Sub


Private Sub Form_Load()
    Dim tAdapterOpen    As D3DKMT_OPENADAPTERFROMHDC
    Dim tWaitVSync      As D3DKMT_WAITFORVERTICALBLANKEVENT
    Dim tAdapterClose   As D3DKMT_CLOSEADAPTER
    Dim lCounter        As Long
    
    Me.Show
    
    ' // Open adapter from HDC
    tAdapterOpen.hDC = Me.hDC
    
    If D3DKMTOpenAdapterFromHdc(tAdapterOpen) < 0 Then
        MsgBox "Unable to open adapter", vbCritical
        Exit Sub
    End If
    
    m_bIsRunning = True
    
    ' // Set wait event param
    tWaitVSync.hAdapter = tAdapterOpen.hAdapter
    tWaitVSync.VidPnSourceId = tAdapterOpen.VidPnSourceId
    
    Do While m_bIsRunning
        
        ' // Wait until vsync
        If D3DKMTWaitForVerticalBlankEvent(tWaitVSync) < 0 Then
            MsgBox "Unable to ait vsync", vbCritical
            Exit Do
        End If
        
        m_lFPSCounter = m_lFPSCounter + 1
        
        ' // To update timer
        DoEvents
        
    Loop
    
    ' // Close adapter
    tAdapterClose.hAdapter = tAdapterOpen.hAdapter
    
    D3DKMTCloseAdapter tAdapterClose
    
End Sub


' // Timer interval = 1000 ms
Private Sub tmrFPS_Timer()
    Me.Caption = "FPS: " & m_lFPSCounter
    m_lFPSCounter = 0
End Sub
```

how can use this in that opengl loop?

about peek message api can send link of that thread?i am use open gl i dont need use directx if need directx  refrences.

----------


## baka

if u can add opengl own vsync it would be best
https://stackoverflow.com/questions/...sync-in-opengl

peekmessage is just this



```
            Do While PeekMessage(uMsg, 0&, 0&, 0&, PM_REMOVE)   ' Reads and deletes message from queue.
                TranslateMessage uMsg                           ' Translates virtual-key messages into character messages.
                DispatchMessage uMsg                            ' Dispatches a message to a window procedure.
            Loop
```

should be many examples if u do a search.

in my game-loop I can use peekmessage to control mouse (so I can use mousewheel) and keys as well.
so I dont need to subclass. but it need to be in a loop or it will not work.

----------


## DataMiser

Just curious what kind of GPU power is on each system?

----------


## Black_Storm

no i am doing complete my project in this thread :

*https://www.vbforums.com/showthread....s-slide-effect*

i just want balance the speed of rotates for all system but as i said in post 1 :
on the CPU dual core win 8 64bit , the speed is good, but in another system like as cput intel core3 win 10 64bit the speed is very slow.
rotate effect processed on cpu dual core in 3 second  and on intel core3 near 6 or 7 second!!!

i attached a demo.zip with 2 exe demo file with once rotate and twice rotate effect for check

actually i dont need peekmessage because i just want show rotate effect for just  short time so no need check keyboards or etc.
i removed sleep and doevents in that opengl in post 1 and i used ctick class from here and like this codes :

*Timed events handler (frame rate control for games etc.)-VBForums
*


```
    lng = FPS.Add(60, 1)
    Dim zoomg As GLfloat
    Dim needexit As Boolean:  needexit = False:  zoomg = -3.08
    
    If FPS.Start Then
        
        Do
            
            Select Case FPS.WaitForNext
            Case lng
                glClear clrColorBufferBit Or clrDepthBufferBit
                
                glLoadIdentity
                glBindTexture GL_TEXTURE_2D, Texture(1)
                glTranslatef 0#, 0#, zoomg
                glRotatef 180, 0, 1, 0
                
                'glColor3f 0.5, 0.5, 1#              ' Set The Color To Blue One Time Only
                glBegin bmQuads
                glTexCoord2f 1#, 1#
                glVertex3f -1#, 1#, 0#
                glTexCoord2f 0#, 1#
                glVertex3f 1#, 1#, 0#
                glTexCoord2f 0#, 0#
                glVertex3f 1#, -1#, 0#
                glTexCoord2f 1#, 0#
                glVertex3f -1#, -1#, 0#
                glEnd
                
                SwapBuffers (frm.hDC) 'Puffer tauschen (Double Buffering)
                'DoEvents
                
                If zoomg = -3.08 Then
                    
                    frmcontrols.visible = False
                    frmparent.visible = False
                    
                End If
                
                zoomg = zoomg - 0.08
                
                If zoomg <= -4 Then needexit = True
                
            End Select
            
        Loop While needexit = False
    End If
    needexit = False
    FPS.RemoveByID 1
```



 with fps 60 or 30 and etc but same result in different systems.
*And it is strange that it works better and faster on an old system with a weaker CPU, but on a stronger system it works weakly and slowly.*

i am work on vsync in opengl and still i am waiting for question in post 3 too and if i should be use directx in my opengl project and api D3DKMTWaitForVerticalBlankEvent  so how can do that too.i jst want balance speed to can run fast smooth on all sytems without different seconds on each systems.

----------


## baka

the reason to use opengl or direct2d/directx is to utilize gpu.
I know nothing about opengl, but in d2d I can pick software(cpu) or hardware(gpu) mode. and of course gpu is the best pick for speed and balance.

now, Im not sure what u are doing exactly. could be u make operations that need cpu, but I mean, u use opengl to avoid that right?

in my game that is 60fps everything is working without problems and I have many layers and tons of animations going on.
and I think opengl would be as fast if I used that. so, not sure whats going on for u and I have too little knowledge to help u.

----------


## Black_Storm

thanks for helps,I know that the hardware capacity can be used in OpenGL and I have not yet entered into the discussion, the reason is that in my project I only do a simple task not like as game design, I only make my forms with a combination of 3D effects. I will combine in OpenGL and design display effects similar to the 3D rotation effect that I designed. In the next steps, I want to add more effects with the help of OpenGL capabilities.

i asked a question in post 3 about D3DKMTWaitForVerticalBlankEvent  and how can use that attached codes if u work on directx and etc. i cant find any sample in vb6 about use D3DKMTWaitForVerticalBlankEvent  and still i dont know how can use that attached codes in post 3 if i had to remove ctick class and replace with that codes.

----------


## baka

I used D3DKMTWaitForVerticalBlankEvent before, but some user reported error with running speed for his computer.
so I reverted back to my "own". here is what I use:

in the "initialization" (that can be used when user is switching between modes) I call:

CustomVSyncInit

and it my "rendering" function (that in d2d is like the "last thing u do" to render the image to the screen, u could say double buffering, as I prepare a bitmap and when everything is done I render it)
I have:
If SoftWare Then CustomVSync



```
Private Type SoftWareData
    Cap()           As Integer
    Caps              As Long
    OneTick         As Long
    OneSec          As Long
    DEX             As Long
End Type

Private Declare Function timeBeginPeriod Lib "winmm.dll" (ByVal uPeriod As Long) As Long
Private Declare Function timeEndPeriod Lib "winmm.dll" (ByVal uPeriod As Long) As Long
Private Declare Function timeGetTime Lib "winmm.dll" () As Long
Private Declare Function GetDeviceCaps Lib "gdi32" (ByVal hDC As Long, ByVal nIndex As Long) As Long

Dim ws                                  As SoftWareData
```



```
Private Sub CustomVSyncInit()
    Dim Ex!, cn!, i&

    With ws
        .Caps = GetDeviceCaps(Main.area.hDC, 116)
        If .OneTick > 0 Then timeEndPeriod 1
        ReDim .Cap(1 To .Caps)
        Ex = 1000 / .Caps
        For i = 1 To .Caps
            cn = cn + Ex
            .Cap(i) = CInt(cn)
        Next i
        timeBeginPeriod 1
        .OneSec = timeGetTime
        .OneTick = 1
    End With
End Sub

Private Sub CustomVSyncTerminate()
    If ws.OneTick > 0 Then timeEndPeriod 1
    ws.OneTick = 0
End Sub

Private Sub CustomVSync()
    With ws
       .DEX = .Cap(.OneTick) + .OneSec
        While timeGetTime < .DEX
            Sleep 1
        Wend
        .OneTick = .OneTick + 1
        If .OneTick > .Caps Then .OneTick = 1: .OneSec = .OneSec + 1000
    End With
End Sub
```

I also give u the code I used for D3DKMTWaitForVerticalBlankEvent 

in initialization u call



```
        tAdapterOpen.hDC = Main.area.hDC
        D3DKMTOpenAdapterFromHdc tAdapterOpen
        tWaitVSync.hAdapter = tAdapterOpen.hAdapter
        tWaitVSync.VidPnSourceId = tAdapterOpen.VidPnSourceId
```

in terminate



```
        tAdapterClose.hAdapter = tAdapterOpen.hAdapter
        D3DKMTCloseAdapter tAdapterClose
```

replace main.area.hdc with anything with a hdc

and before rendering I use



```
If SoftWare Then D3DKMTWaitForVerticalBlankEvent tWaitVSync
```

but this only works if u have a loop.
so, what u do is, when u call any effect. everything in your form should be "paused"
meaning, u can not have any doevents, refresh, paint-events etc. that will slow your program a lot.
so u call a "loop" that will "exit" when the animation is done. after that u resume the program.
not sure here, if u copy the form(screenshot). if so, hide/disable the form after u do that, and show when the animation is done.

----------


## Schmidt

Since the question is: "how can the execution *speed* of loop *be the same*"...

I wonder why no one is addressing the elephant in the room...
which is "simply physics": *v = s / t* 

And when *v* shall be a "*constant speed*" (e.g. set at "90 RotationDegrees per second"),
then the adaption would be
delta_Degrees = constant_v * delta_TimeBetweenLoopIterationsInSeconds

This will work with a timer-based gameloop (no matter what Timer.Interval you set) - 
and also with a VSync-based loop (where the Screenefresh-rate might be different between machines)

Olaf

----------


## baka

I use it in my "formula" as u see Ex = 1000 / .Caps
and the reason I create an array is so, even if one frame is out of sync, it will adjust itself in the next or the next.
this works quite well in my game when using software mode. and the users have all kinds of monitors frequency.

----------


## Black_Storm

i found some modules in vb6 about how can enable vsync in opengl but its need converts my project to can compatible with that opengl version and it make it hard .i temporary used like below codes and checked on some different systems and its work good i testes with run mulitple program in same time too and its work good again.



```

Static r4eckY As GLfloat:      r4eckY = 180
    Dim needunload As Boolean: needunload = True
    Ticks_Per_Second = 0: Start_Time = 0: Milliseconds = 0
    QueryPerformanceFrequency Ticks_Per_Second
    QueryPerformanceCounter Start_Time
    Milliseconds = Time
    Do
        DoEvents
        Lock_Framerate 60
        
        glClear clrColorBufferBit Or clrDepthBufferBit
        glLoadIdentity
        
        If r4eckY = 2 * 90 Then glBindTexture GL_TEXTURE_2D, Texture(1)
        glTranslatef 0#, 0#, zoomg
        
        If r4eckY > (5 * 90) Then
            r4eckY = 450
            needexit = True
            PrgRun = False
        End If
        
        glRotatef r4eckY, 0, 1, 0
        
        
        glBegin bmQuads
        glTexCoord2f 1#, 1#
        glVertex3f -1#, 1#, 0#
        glTexCoord2f 0#, 1#
        glVertex3f 1#, 1#, 0#
        glTexCoord2f 0#, 0#
        glVertex3f 1#, -1#, 0#
        glTexCoord2f 1#, 0#
        glVertex3f -1#, -1#, 0#
        glEnd
        
        SwapBuffers (frm.hDC)
        If frm.Visible = False Then frm.Visible = True
        
        If needunload Then needunload = False
        r4eckY = r4eckY + 4
        QueryPerformanceCounter Start_Time
    Loop While needexit = False
```

i changed speed too like below :


```
        r4eckY = r4eckY + 4
```

so, i resolved this thread,thanks for helps and now i have another question in following my project here about take screen shot outside of screen:
*How can take screen shot of special area outside of desktop?-VBForums*

----------

