Plot VS Sprite VS Poke
On en a déjà parlé plusieurs fois sur les divers forums. Le fait d'accéder directement à la mémoire graphique avec le processeur est (en général) particulièrement lent. Il vaut mieux travailler soit avec les APIs (directx ou opengl), soit travailler en mémoire centrale, et envoyer le tout d'un coup (comme fait fred pour les opérations spéciales sur les sprites).
Le problème des API windows c'est que ce n'est pas compatible linux/MacOsX...djes a écrit :On en a déjà parlé plusieurs fois sur les divers forums. Le fait d'accéder directement à la mémoire graphique avec le processeur est (en général) particulièrement lent. Il vaut mieux travailler soit avec les APIs (directx ou opengl), soit travailler en mémoire centrale, et envoyer le tout d'un coup (comme fait fred pour les opérations spéciales sur les sprites).

OpenGL est présent partout. Il n'y a qu'à modifier l'initialisation. Pour le reste, on peut se servir des macros. On peut aussi faire un subsystem... Voir celui-ci qui a l'air particulièrement prometteur : http://www.purebasic.fr/english/viewtop ... ht=directx
Quelques petits tests de remplissage ajoutés au code de CplBator. Pas eu le temps d'adapter l'opengl.
Code : Tout sélectionner
;Original code by CplBator
Structure DrawingInfoStruct
Type.l
Window.l
DC.l
ReleaseProcedure.l
PixelBuffer.l
Pitch.l
Width.l
Height.l
Depth.l
PixelFormat.l
StopDirectAccess.l
StartDirectAccess.l
EndStructure
Global FastImgOutputID.DrawingInfoStruct
;By Rescator
Procedure.l Ticks_HQ()
Static maxfreq.q
Protected t.q
If maxfreq=0
QueryPerformanceFrequency_(@maxfreq)
maxfreq=maxfreq/1000
EndIf
QueryPerformanceCounter_(@t.q)
ProcedureReturn t/maxfreq
EndProcedure
Procedure ___ReleaseFastImageOutput()
If FastImgOutputID\DC:DeleteDC_(FastImgOutputID\DC):FastImgOutputID\DC=0:EndIf ; free the created memory DC
EndProcedure
Procedure ___StopDirectAccess()
ProcedureReturn FastImgOutputID\DC
EndProcedure
Procedure ___StartDirectAccess()
GetPixel_(FastImgOutputID\DC,0,0) ; make sure all GDI operations are finished
ProcedureReturn FastImgOutputID\PixelBuffer
EndProcedure
; FastImageOutput() provides a faster pixel access for 32-,24- and 15 bit images(DIBSesctions).
; However, for now only plot(x,y,color) works faster. (point(x,y) seems to be not optimized for direct memory access at the moment. You can use the PointFast() command from the E2D Userlib to get a faster point command.)
Procedure FastImageOutput(Image)
If GetObject_(ImageID(Image),SizeOf(DIBSECTION),ds.DIBSECTION)=0
ProcedureReturn 0 ; no DIBSECTION
EndIf
FastImgOutputID\Type=7 ; allows direct memory access
FastImgOutputID\ReleaseProcedure=@___ReleaseFastImageOutput()
FastImgOutputID\PixelBuffer=ds\dsBm\bmBits+ds\dsBm\bmWidthBytes*(ds\dsBm\bmHeight-1) ;needed because the image if top down
FastImgOutputID\Pitch=-ds\dsBm\bmWidthBytes
FastImgOutputID\Width=ds\dsBm\bmWidth
FastImgOutputID\Height=ds\dsBm\bmHeight
FastImgOutputID\Depth=ds\dsBm\bmBitsPixel
Select FastImgOutputID\Depth
Case 32
FastImgOutputID\PixelFormat=#PB_PixelFormat_32Bits_BGR
Case 24
FastImgOutputID\PixelFormat=#PB_PixelFormat_24Bits_BGR
Case 16
FastImgOutputID\Depth=15
FastImgOutputID\PixelFormat=#PB_PixelFormat_15Bits
Default
ProcedureReturn 0 ; only 32-,24- and 15bit DIBSections are supported
EndSelect
MemDC=CreateCompatibleDC_(0)
If MemDC=0:ProcedureReturn 0:EndIf ; the memory DC cannot be created
SelectObject_(MemDC,ImageID(Image))
FastImgOutputID\DC=MemDC
FastImgOutputID\StopDirectAccess=@___StopDirectAccess()
FastImgOutputID\StartDirectAccess=@___StartDirectAccess()
ProcedureReturn FastImgOutputID
EndProcedure
InitSprite()
OpenScreen(800,600,32,"PEEK AND POKE VS POINTER :D ")
Structure Pixel
Pixel.l
EndStructure : Global *Ptr.Pixel : Global *Poke.l
Declare PointerDraw()
Declare PokeDraw()
Declare SpritePointerDraw()
Declare SpritePointerDrawFX()
Declare SpritePokeDraw()
Declare FastImg()
PTR.l = PointerDraw()
PKE.l = PokeDraw()
SPR.l = SpritePointerDraw()
SPX.l = SpritePointerDrawFX()
SPD.l = SpritePokeDraw()
FIM.l = FastImg()
CloseScreen()
MessageRequester("","POINTEUR = "+Str(PTR)+"ms"+Chr(10)+"POKE = "+Str(PKE)+"ms"+Chr(10)+"SPRPTR = "+Str(SPR)+"ms"+Chr(10)+"SPRPTRFX = "+Str(SPX)+"ms"+Chr(10)+"SPRPOKDR = "+Str(SPD)+"ms"+Chr(10)+"FASTIMG = "+Str(FIM)+"ms")
Procedure PointerDraw()
Protected DBuffer.l,DBufferP.l,PixelFormat.l,Pbyte.l
Protected TA.l,TB.l
StartDrawing(ScreenOutput())
DBuffer = DrawingBuffer()
DBufferP = DrawingBufferPitch()
PixelFormat = DrawingBufferPixelFormat()
StopDrawing()
Select PixelFormat
Case #PB_PixelFormat_8Bits : PixelFormat=1
Case #PB_PixelFormat_15Bits : PixelFormat=2
Case #PB_PixelFormat_16Bits : PixelFormat=2
Case #PB_PixelFormat_24Bits_RGB : PixelFormat=3
Case #PB_PixelFormat_24Bits_BGR : PixelFormat=3
Case #PB_PixelFormat_32Bits_RGB : PixelFormat=4
Case #PB_PixelFormat_32Bits_BGR : PixelFormat=4
EndSelect
diff.l = DBufferP-800*PixelFormat
TA=Ticks_HQ()
For i = 1 To 300
*Ptr = DBuffer
For y = 0 To 600-1
v.l=RGB(0,y*i,0)
For x = 0 To 800-1
*Ptr\Pixel = v
*Ptr + PixelFormat
Next
*Ptr+diff
Next
FlipBuffers()
Next i
TB=Ticks_HQ()
ProcedureReturn TB-TA
EndProcedure
Procedure PokeDraw()
Protected DBuffer.l,DBufferP.l,PixelFormat.l,Pbyte.l
Protected TA.l,TB.l
StartDrawing(ScreenOutput())
DBuffer = DrawingBuffer()
DBufferP = DrawingBufferPitch()
PixelFormat = DrawingBufferPixelFormat()
StopDrawing()
Select PixelFormat
Case #PB_PixelFormat_8Bits : PixelFormat=1
Case #PB_PixelFormat_15Bits : PixelFormat=2
Case #PB_PixelFormat_16Bits : PixelFormat=2
Case #PB_PixelFormat_24Bits_RGB : PixelFormat=3
Case #PB_PixelFormat_24Bits_BGR : PixelFormat=3
Case #PB_PixelFormat_32Bits_RGB : PixelFormat=4
Case #PB_PixelFormat_32Bits_BGR : PixelFormat=4
EndSelect
diff.l = DBufferP-800*PixelFormat
TA=Ticks_HQ()
For i = 1 To 300
*Poke = DBuffer
For y = 0 To 600-1
v.l=RGB(y*i,0,0)
For x = 0 To 800-1
PokeL(*Poke,v)
*Poke + PixelFormat
Next
*Poke+diff
Next
FlipBuffers()
Next i
TB=Ticks_HQ()
ProcedureReturn TB-TA
EndProcedure
Procedure SpritePointerDraw()
Protected DBuffer.l,DBufferP.l,PixelFormat.l,Pbyte.l
Protected TA.l,TB.l
mem_spr.l=CreateSprite(#PB_Any,800,600,#PB_Sprite_Memory|#PB_Sprite_Alpha)
StartDrawing(SpriteOutput(mem_spr))
DBuffer = DrawingBuffer()
DBufferP = DrawingBufferPitch()
PixelFormat = DrawingBufferPixelFormat()
StopDrawing()
Select PixelFormat
Case #PB_PixelFormat_8Bits : PixelFormat=1
Case #PB_PixelFormat_15Bits : PixelFormat=2
Case #PB_PixelFormat_16Bits : PixelFormat=2
Case #PB_PixelFormat_24Bits_RGB : PixelFormat=3
Case #PB_PixelFormat_24Bits_BGR : PixelFormat=3
Case #PB_PixelFormat_32Bits_RGB : PixelFormat=4
Case #PB_PixelFormat_32Bits_BGR : PixelFormat=4
EndSelect
diff.l = DBufferP-800*PixelFormat
TA=Ticks_HQ()
For i = 1 To 300
*Ptr = DBuffer
For y = 0 To 600-1
v.l=RGB(0,y*i,0)
For x = 0 To 800-1
*Ptr\Pixel = v
*Ptr + PixelFormat
Next
*Ptr+diff
Next
DisplaySprite(mem_spr,0,0)
FlipBuffers()
Next i
TB=Ticks_HQ()
ProcedureReturn TB-TA
EndProcedure
Procedure SpritePointerDrawFX()
Protected DBuffer.l,DBufferP.l,PixelFormat.l,Pbyte.l
Protected TA.l,TB.l
mem_spr.l=CreateSprite(#PB_Any,800,600,#PB_Sprite_Memory|#PB_Sprite_Alpha)
StartDrawing(SpriteOutput(mem_spr))
DBuffer = DrawingBuffer()
DBufferP = DrawingBufferPitch()
PixelFormat = DrawingBufferPixelFormat()
StopDrawing()
Select PixelFormat
Case #PB_PixelFormat_8Bits : PixelFormat=1
Case #PB_PixelFormat_15Bits : PixelFormat=2
Case #PB_PixelFormat_16Bits : PixelFormat=2
Case #PB_PixelFormat_24Bits_RGB : PixelFormat=3
Case #PB_PixelFormat_24Bits_BGR : PixelFormat=3
Case #PB_PixelFormat_32Bits_RGB : PixelFormat=4
Case #PB_PixelFormat_32Bits_BGR : PixelFormat=4
EndSelect
diff.l = DBufferP-800*PixelFormat
StartSpecialFX()
TA=Ticks_HQ()
For i = 1 To 300
*Ptr = DBuffer
For y = 0 To 600-1
v.l=RGB(0,0,y*i)
For x = 0 To 800-1
*Ptr\Pixel = v
*Ptr + PixelFormat
Next
*Ptr+diff
Next
DisplaySprite(mem_spr,0,0)
FlipBuffers()
Next i
TB=Ticks_HQ()
StopSpecialFX()
ProcedureReturn TB-TA
EndProcedure
Procedure SpritePokeDraw()
Protected DBuffer.l,DBufferP.l,PixelFormat.l,Pbyte.l
Protected TA.l,TB.l
mem_spr.l=CreateSprite(#PB_Any,800,600,#PB_Sprite_Memory|#PB_Sprite_Alpha)
StartDrawing(SpriteOutput(mem_spr))
DBuffer = DrawingBuffer()
DBufferP = DrawingBufferPitch()
PixelFormat = DrawingBufferPixelFormat()
StopDrawing()
Select PixelFormat
Case #PB_PixelFormat_8Bits : PixelFormat=1
Case #PB_PixelFormat_15Bits : PixelFormat=2
Case #PB_PixelFormat_16Bits : PixelFormat=2
Case #PB_PixelFormat_24Bits_RGB : PixelFormat=3
Case #PB_PixelFormat_24Bits_BGR : PixelFormat=3
Case #PB_PixelFormat_32Bits_RGB : PixelFormat=4
Case #PB_PixelFormat_32Bits_BGR : PixelFormat=4
EndSelect
diff.l = DBufferP-800*PixelFormat
TA=Ticks_HQ()
For i = 1 To 300
*Poke = DBuffer
For y = 0 To 600-1
v.l=RGB(y*i,0,0)
For x = 0 To 800-1
PokeL(*Poke,v)
*Poke + PixelFormat
Next
*Poke+diff
Next
DisplaySprite(mem_spr,0,0)
FlipBuffers()
Next i
TB=Ticks_HQ()
ProcedureReturn TB-TA
EndProcedure
Procedure FastImg()
CreateImage(1,800,600,32) ; only 32bit seems to be really faster...
TA=Ticks_HQ()
For i = 1 To 300
StartDrawing(FastImageOutput(1)) ; replace this by ImageOutput(1)
For y = 0 To 600-1
v.l=RGB(y*i,0,0)
For x = 0 To 800-1
Plot(x,y,v)
Next
Next
StopDrawing()
StartDrawing(ScreenOutput())
DrawImage(ImageID(1),0,0)
StopDrawing()
FlipBuffers()
Next i
TB=Ticks_HQ()
StopDrawing()
ProcedureReturn TB-TA
EndProcedure
fait attention avec tes codes, djes, j ai fait une crise epilepsie.
bien failli me sectionner la langue ,moi!!
il a bien changé le "poke".., mon temps (heu..! pas si longtemps quant meme) le "poke" ecrivait directement sur la memoire.
maintenant, un "pokel" desassemblé donne ca:
PUSH dword [esp+36]
MOV eax,dword [p_Poke]
CALL PB_PokeL
ici, deux lecture memoire et un saut vers une procedure.
pas étonnant que que la vitesse du plot et du pokel, ce valent .

bien failli me sectionner la langue ,moi!!
il a bien changé le "poke".., mon temps (heu..! pas si longtemps quant meme) le "poke" ecrivait directement sur la memoire.
maintenant, un "pokel" desassemblé donne ca:
PUSH dword [esp+36]
MOV eax,dword [p_Poke]
CALL PB_PokeL
ici, deux lecture memoire et un saut vers une procedure.
pas étonnant que que la vitesse du plot et du pokel, ce valent .
Oui je sais, j'en ai déjà parlé à Fred. Même chose pour les listes chainées, y'a des sauts partout! Là on a pris du code PB simple, sans assembleur.tonton a écrit :fait attention avec tes codes, djes, j ai fait une crise epilepsie.![]()
bien failli me sectionner la langue ,moi!!
il a bien changé le "poke".., mon temps (heu..! pas si longtemps quant meme) le "poke" ecrivait directement sur la memoire.
maintenant, un "pokel" desassemblé donne ca:
PUSH dword [esp+36]
MOV eax,dword [p_Poke]
CALL PB_PokeL
ici, deux lecture memoire et un saut vers une procedure.
pas étonnant que que la vitesse du plot et du pokel, ce valent .
Merci pour ce debat passionnant...
Faisons le point en posant cette question : finalement, l'affichage le plus rapide n'est il pas l'envoie de toute une banque de données dans la memoire video ?? (similaire aux pokes si je ne m'abuse...)
Maintenant, une question sur les sprites. En observant les images des meteorites du jeu INTRUDERS, on s'appercois qu'elles sont toutes en largeur et contiennent sur cette largeur toutes les images formant l'animation de chaque meteorite.
Alors, comme je sais qu'on peux faire un ClipSprite pour n'afficher qu'une partie de ce sprite, la tentation est grande de créer un seul sprite contenant toutes les images de l'anim de la meteorite et d'utiliser ClipSprite pour afficher seulement la bonne sequence de l'anim.
Mais est-ce preferable par rapport a la methode classique qui consiste a mettre l'anim sur plusieurs sprites ?????
Faisons le point en posant cette question : finalement, l'affichage le plus rapide n'est il pas l'envoie de toute une banque de données dans la memoire video ?? (similaire aux pokes si je ne m'abuse...)
Maintenant, une question sur les sprites. En observant les images des meteorites du jeu INTRUDERS, on s'appercois qu'elles sont toutes en largeur et contiennent sur cette largeur toutes les images formant l'animation de chaque meteorite.
Alors, comme je sais qu'on peux faire un ClipSprite pour n'afficher qu'une partie de ce sprite, la tentation est grande de créer un seul sprite contenant toutes les images de l'anim de la meteorite et d'utiliser ClipSprite pour afficher seulement la bonne sequence de l'anim.
Mais est-ce preferable par rapport a la methode classique qui consiste a mettre l'anim sur plusieurs sprites ?????
des questions...(peut être idiotes ?!
) est ce que ça ne serait pas plus performant d'utiliser conjointement les pointeurs/pokes avec les fonctions startSpecialFX() et stopSpecialFx() ou en travaillant sur un sprite crééer avec l'option #PB_Sprite_Memory ?
J'ai fait des tests pour statSpecialFx() mais je n'ai qu'un ecran noir...et ça ne change rien au perf...je ne sais pas si je l'utilise bien. j'ai jammais bien compris ce qui se passait lorsqu'on utilisait ces fonctions...
Autre question quelqu'un ne pourrait il pas faire une fonction Poke en assembleur plus rapide puisqu'apparment, PB ne vas pas au plus simple ?
Je travaille toujours sur des effets 2d (lumière) ou je dois travailler au pixel...je cherche donc toujours a optimisé !

J'ai fait des tests pour statSpecialFx() mais je n'ai qu'un ecran noir...et ça ne change rien au perf...je ne sais pas si je l'utilise bien. j'ai jammais bien compris ce qui se passait lorsqu'on utilisait ces fonctions...
Autre question quelqu'un ne pourrait il pas faire une fonction Poke en assembleur plus rapide puisqu'apparment, PB ne vas pas au plus simple ?
Je travaille toujours sur des effets 2d (lumière) ou je dois travailler au pixel...je cherche donc toujours a optimisé !

Les pointeurs sont plus rapides que les POKE, quand on travaille avec la mémoire cache il n'y a aucun doute. Quand on travaille avec la mémoire vidéo, on est limité par la bande passante inférieure à celle de la mémoire cache. Là, le transfert de données est plafonné et le microprocesseur a largement le temps d'exécuter des POKE...