Exe : http://djes.free.fr/purebasic/rasterlines.exe
N'oubliez pas de mettre DirectX9 dans Compilateur -> Options du compilateur -> Bibliothèque sous-système
[Edit] Petite explication : vous allez voir à l'écran un effet (ici, des cercles qui vont de droite à gauche, un peu comme un champ d'étoiles), et deux lignes. Ces deux lignes indiquent le temps que prend l'effet, en se basant sur l'affichage comme base de temps. C'est un vieux truc de démomakers.
L'espace entre les deux lignes correspond au temps pris par l'ordinateur pour calculer et afficher notre effet.
Pour comprendre, il faut se rappeller comment fonctionnent les écrans CRT : l'écran est un tube cathodique, dont la surface est recouverte de phosphore, matériau qui émet de la lumière quand il reçoit un faisceau d'électrons. Ce faisceau est appelé "spot". Le spot parcourt donc la surface de haut en bas, et de gauche à droite. Pour un affichage à 60imgs par seconde, il fait donc cela 60 fois par seconde (simple, non?), c'est ce que vous voyez dans les paramètres d'affichage : 60hz.
Ce que fait ce programme est de synchroniser le code sur la position du spot. Il commence le code en haut après le clearscreen et affiche une première ligne. Ensuite il calcule et affiche les sprites dans le backbuffer, et affiche la nouvelle position du spot : deuxième ligne. Donc on voit que notre effet a demandé un certain temps à notre malheureux PC! Plus vous ferez de calculs, ou afficherez de sprites, plus la deuxième ligne descendra...
Si vous atteignez le bas, vous aurez ce qu'on appelle un "frame drop" : l'ordi ne peut pas tout afficher en moins d'une frame, donc au lieu d'avoir un bel affichage à 60 imgs/secs, vous passez à 30 imgs/secs, d'où l'effet de "saut" assez désagréable que détestent les vrais démomakers!
Si votre écran est à 60Hz, que vous avez moins de la hauteur d'un écran entre les deux lignes, cela signifie que l'effet a pris moins de 16 ms, et que nous avons donc nos 60 imgs/sec et la meilleure fluidité possible!

[Edit2] PB 4.60 et nettoyage
Code : Tout sélectionner
;*****************************************************************************
;* RasterLine and vertical blank (VBL) benchmark
;* Realtime visual benchmark. Press space to add "stars". The time is given
;* by the space between blue and green line.
;* By djes (djes@free.fr) 03/24/2009
;* Thanx to Stefan Moebius for VBL sync examples
;* Note : I do not check functions return values : I know it's bad!!!
;* 02/28/2012 : PB 4.60 fix
;*****************************************************************************
Structure D3DRaster_STATUS
InVBlank.l
ScanLine.l
EndStructure
Structure Pos
x.l
y.l
Speed.l
EndStructure
;*****************************************************************************
Define.D3DRaster_STATUS Raster
Define.IDirect3DDevice9 D3DDeviceInterface
Global NewList Stars.Pos()
;*****************************************************************************
;wait for the vblank to start - takes all the cpu
;attend le début de la synchro vbl
Procedure VBLWait()
Shared D3DDeviceInterface, Raster, Exit
Repeat
ExamineKeyboard()
If KeyboardPushed(#PB_Key_Escape)
Exit=#True
EndIf
D3DDeviceInterface\GetRasterStatus(0, @Raster)
Until Raster\InVBlank=#True Or Exit
EndProcedure
;*****************************
;wait for the vblank to finish - takes all the cpu
;attend la fin de la synchro vbl
Procedure VBLEndWait()
Shared D3DDeviceInterface, Raster, Exit
Repeat
ExamineKeyboard()
If KeyboardPushed(#PB_Key_Escape)
Exit=#True
EndIf
D3DDeviceInterface\GetRasterStatus(0, @Raster)
Until Raster\InVBlank=#False Or Exit
EndProcedure
;*****************************
;look for the Raster pos and draw a coloured line
;récupère la position du Raster et y affiche une ligne de la couleur indiquée
Procedure RasterLine(Color.l)
Shared Raster, D3DDeviceInterface
StartDrawing(ScreenOutput())
D3DDeviceInterface\GetRasterStatus(0, @Raster)
LineXY(0, Raster\ScanLine, 1023, Raster\ScanLine, Color)
StopDrawing()
EndProcedure
;**************************
Procedure CreateSprites()
CreateSprite(0, 64, 64)
StartDrawing(SpriteOutput(0))
Circle(32, 32, 31, RGB($FF, $FF, $FF))
StopDrawing()
EndProcedure
;************************
;Open screen and get the device - Ouvre l'écran et récupère le device
Procedure InitDisplay()
Shared D3DDeviceInterface
OpenScreen(1024, 768, 32, "", #PB_Screen_NoSynchronization, 60)
!extrn _PB_Screen_Direct3DDevice
!MOV dword EAX, [_PB_Screen_Direct3DDevice]
!MOV dword [v_D3DDeviceInterface],EAX
EndProcedure
;************************
;Check if the user has switched (and that we have lost focus) (ALT-TAB)
;Vérifie si l'utilisateur n'a pas changé d'appli (en nous faisant donc perdre le focus) (ALT-TAB)
Procedure FullScreenCheck()
;we're lowering our priority - on baisse notre priorité
SetPriorityClass_( GetCurrentProcess_(), #NORMAL_PRIORITY_CLASS)
SetThreadPriority_( GetCurrentThread_() , #THREAD_PRIORITY_NORMAL)
ReleaseMouse(1)
CloseScreen()
OpenWindow(0, 0, 0, 256, 256, "RasterLines", #PB_Window_Minimize)
;Wait til our window is coming back to foreground - Attend que notre fenêtre repasse au premier plan
Repeat
;now our events are to be processed with WaitWindowEvent, else IsScreenActive() will never say that our window has the focus again
;it should be written in the doc!
;maintenant les événements sont à gérer avec WaitWindowEvent, sinon IsScreenActive() ne dit jamais que notre fenêtre a à nouveau le focus
;il faudrait mettre ça dans la doc!!!!
Event = WaitWindowEvent()
Until Event = #PB_Event_ActivateWindow
CloseWindow(0)
ReleaseMouse(0)
;Better recreate the screen - il vaut mieux recréer l'écran
InitDisplay()
;and the sprites too (have to!) - et les sprites aussi (indispensable)
CreateSprites()
;give to the system some time to rest - laisse un peu le temps au système de récupérer
;Delay(2000)
;We're waiting for the synchro a new time - On réattend la synchro
VBLWait()
SetPriorityClass_( GetCurrentProcess_(), #HIGH_PRIORITY_CLASS)
SetThreadPriority_( GetCurrentThread_() , #THREAD_PRIORITY_ABOVE_NORMAL) ;warning : keyboard lock
EndProcedure
Procedure NewStar()
AddElement(Stars())
Stars()\x = Random(1024 + 128) - 64
Stars()\y = Random(768 + 128) - 64
Stars()\Speed = Random(16) + 1
EndProcedure
;*****************************************************************************
;- START
;*****************************************************************************
InitSprite()
InitKeyboard()
InitMouse()
InitDisplay()
CreateSprites()
For i = 1 To 5
NewStar()
Next i
Exit=#False
;we're giving max priority to our process - on donne une priorité maximale à notre processus
SetPriorityClass_( GetCurrentProcess_(), #REALTIME_PRIORITY_CLASS)
SetThreadPriority_( GetCurrentThread_() , #THREAD_PRIORITY_TIME_CRITICAL) ;warning : keyboard lock
;*****************************************************************************
;- MAIN LOOP
;*****************************************************************************
Repeat
;wait for the sync - attends la synchro
VBLWait()
;flip buffers without the PB's sync - flippe le buffer sans utiliser la synchro PB
FlipBuffers()
;during VBL, lower a bit our priority to give time to OS (especially to handle the keyboard)
;pendant la VBL, baisse un peu notre priorité pour donner un peu de temps au système (pour gérer le clavier surtout)
SetPriorityClass_( GetCurrentProcess_(), #HIGH_PRIORITY_CLASS)
SetThreadPriority_( GetCurrentThread_() , #THREAD_PRIORITY_NORMAL)
ExamineKeyboard()
ExamineMouse()
If KeyboardPushed(#PB_Key_Escape)
Exit=#True
EndIf
If KeyboardPushed(#PB_Key_Space)
NewStar()
EndIf
If Not IsScreenActive()
FullScreenCheck()
EndIf
;we're waiting for the VBL end (could be better!!!)
;on attend la fin de la VBL (à améliorer) pour être sûr de ne pas sauter une frame
VBLEndWait()
;we're giving max priority to our process - on donne une priorité maximale à notre processus
SetPriorityClass_( GetCurrentProcess_(), #REALTIME_PRIORITY_CLASS)
SetThreadPriority_( GetCurrentThread_() , #THREAD_PRIORITY_TIME_CRITICAL) ;warning : keyboard lock
ClearScreen(0)
;--- BENCHMARK
;draw the first Raster line (base of our benchmark)
RasterLine($FF0000)
;compute an effect
ForEach Stars()
Stars()\x + Stars()\Speed
If Stars()\x > 1023
Stars()\x - 1088
EndIf
Next
;display it
ForEach Stars()
DisplayTranslucentSprite(0, Stars()\x, Stars()\y, Stars()\Speed<<4)
Next
;draw the second RasterLine to see (visually) how much time our fx is taking
;the less space between the two lines, the fastest our effect
;affiche une RasterLine pour visualiser combien de temps prend notre effet
RasterLine($FF00)
;---- BENCHMARK END
StartDrawing(ScreenOutput())
DrawingMode(#PB_2DDrawing_Transparent)
Text.s = "Press SPACE to add stars ; ESC to quit"
DrawText(512 - TextWidth(Text)/2, 300, Text, #Blue)
Text.s = "Stars Nb : " + Str(ListSize(Stars()))
DrawText(512 - TextWidth(Text)/2, 320, Text, #Red)
StopDrawing()
Until Exit
CloseScreen()
End