Plot VS Sprite VS Poke

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message par djes »

Surtout que comme j'en ai déjà parlé il y a un moment, le code doit être aligné correctement si on veut avoir quelque chose de vraiment comparable...
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

j'obtiens bien un meilleur score avec les pointeurs...
en moyenne : 3600ms pout les pointeurs et 3800 pour les poke

Dri
Anonyme

Message par Anonyme »

Cela doit dépendre de l'architecture des processeurs, pas facile donc de faire de l'optimisation, il faudrait trouvé le type de proc, puis codé en fonction... :?
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

sur mon pc j'ai les Pokes qui gagne légèrement, et sur mon portable c'est l'inverse...comme quoi ... :lol:
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message par djes »

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).
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

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).
Le problème des API windows c'est que ce n'est pas compatible linux/MacOsX... :(
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message par djes »

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
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message par djes »

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
tonton
Messages : 315
Inscription : mar. 26/avr./2005 15:19

Message par tonton »

fait attention avec tes codes, djes, j ai fait une crise epilepsie. :roll:
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 .
Avatar de l’utilisateur
Flype
Messages : 2431
Inscription : jeu. 29/janv./2004 0:26
Localisation : Nantes

Message par Flype »

ben, tu peux toujours programmer en asm si tu veux.
Image
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message par djes »

tonton a écrit :fait attention avec tes codes, djes, j ai fait une crise epilepsie. :roll:
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.
Avatar de l’utilisateur
SPH
Messages : 4945
Inscription : mer. 09/nov./2005 9:53

Message par SPH »

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 ?????
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

bah je dirais qu'avec un seul fichier, tu as un seul sprite, donc une seule surface directx donc un seul acces pour afficher toutes tes météorites quels que soient leurs position dans l'animation. donc plus performant.

(c'est là tout l'intérêt du clipsprite...)

Dri
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

des questions...(peut être idiotes ?! :roll: ) 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é ! :P
erix14
Messages : 480
Inscription : sam. 27/mars/2004 16:44
Contact :

Message par erix14 »

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...
Répondre